Spark:DataFrame 写入文本文件
将DataFrame写成文件方法有很多
最简单的将DataFrame转换成RDD,通过saveASTextFile进行保存但是这个方法存在一些局限性:
1.将DataFrame转换成RDD或导致数据结构的改变
2.RDD的saveASTextFile如果文件存在则无法写入,也就意味着数据只能覆盖无法追加,对于有数据追加需求的人很不友好
3.如果数据需要二次处理,RDD指定分隔符比较繁琐
基于以上原因,在研读了Spark的官方文档后,决定采取DataFrame的自带方法 write 来实现。
此处采用mysql的数据作为数据源,读取mysql的方法在 Spark:读取mysql数据作为DataFrame 有详细介绍。
1.mysql的信息
mysql的信息我保存在了外部的配置文件,这样方便后续的配置添加。
//配置文件示例:
[hdfs@iptve2e03 tmp_lillcol]$ cat job.properties
#mysql数据库配置
mysql.driver=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://127.0.0.1:3306/database1?useSSL=false&autoReconnect=true&failOverReadOnly=false&rewriteBatchedStatements=true
mysql.username=user
mysql.password=123456
2.需要的jar依赖
sbt版本,maven的对应修改即可
libraryDependencies += "org.apache.spark" % "spark-core_2.10" % "1.6.0-cdh5.7.2"
libraryDependencies += "org.apache.spark" % "spark-sql_2.10" % "1.6.0-cdh5.7.2"
libraryDependencies += "org.apache.spark" % "spark-hive_2.10" % "1.6.0-cdh5.7.2"
libraryDependencies += "org.apache.hbase" % "hbase-client" % "1.2.0-cdh5.7.2"
libraryDependencies += "org.apache.hbase" % "hbase-server" % "1.2.0-cdh5.7.2"
libraryDependencies += "org.apache.hbase" % "hbase-common" % "1.2.0-cdh5.7.2"
libraryDependencies += "org.apache.hbase" % "hbase-protocol" % "1.2.0-cdh5.7.2"
libraryDependencies += "mysql" % "mysql-connector-java" % "5.1.38"
libraryDependencies += "org.apache.spark" % "spark-streaming_2.10" % "1.6.0-cdh5.7.2"
libraryDependencies += "com.yammer.metrics" % "metrics-core" % "2.2.0"
3.完整实现代码
import java.io.FileInputStream
import java.util.Properties import org.apache.spark.sql.hive.HiveContext
import org.apache.spark.sql.{DataFrame, SQLContext, SaveMode}
import org.apache.spark.{SparkConf, SparkContext} /**
* @author Administrator
* 2018/10/16-14:35
*
*/
object TestSaveFile {
var hdfsPath: String = ""
var proPath: String = ""
var DATE: String = "" val sparkConf: SparkConf = new SparkConf().setAppName(getClass.getSimpleName)
val sc: SparkContext = new SparkContext(sparkConf)
val sqlContext: SQLContext = new HiveContext(sc) def main(args: Array[String]): Unit = {
hdfsPath = args(0)
proPath = args(1)
//不过滤读取
val dim_sys_city_dict: DataFrame = readMysqlTable(sqlContext, "TestMysqlTble1", proPath)
saveAsFileAbsPath(dim_sys_city_dict, hdfsPath + "TestSaveFile", "|", SaveMode.Overwrite)
} /**
* 获取 Mysql 表的数据
*
* @param sqlContext
* @param tableName 读取Mysql表的名字
* @param proPath 配置文件的路径
* @return 返回 Mysql 表的 DataFrame
*/
def readMysqlTable(sqlContext: SQLContext, tableName: String, proPath: String): DataFrame = {
val properties: Properties = getProPerties(proPath)
sqlContext
.read
.format("jdbc")
.option("url", properties.getProperty("mysql.url"))
.option("driver", properties.getProperty("mysql.driver"))
.option("user", properties.getProperty("mysql.username"))
.option("password", properties.getProperty("mysql.password"))
.option("dbtable", tableName)
.load()
} /**
* 将 DataFrame 保存为 hdfs 文件 同时指定保存绝对路径 与 分隔符
*
* @param dataFrame 需要保存的 DataFrame
* @param absSaveDir 保存保存的路径 (据对路径)
* @param splitRex 指定分割分隔符
* @param saveMode 保存的模式:Append、Overwrite、ErrorIfExists、Ignore
*/
def saveAsFileAbsPath(dataFrame: DataFrame, absSaveDir: String, splitRex: String, saveMode: SaveMode): Unit = {
dataFrame.sqlContext.sparkContext.hadoopConfiguration.set("mapred.output.compress", "false")
//为了方便观看结果去掉压缩格式
val allClumnName: String = dataFrame.columns.mkString(",")
val result: DataFrame = dataFrame.selectExpr(s"concat_ws('$splitRex',$allClumnName) as allclumn")
result.write.mode(saveMode).text(absSaveDir)
} /**
* 获取配置文件
*
* @param proPath
* @return
*/
def getProPerties(proPath: String): Properties = {
val properties: Properties = new Properties()
properties.load(new FileInputStream(proPath))
properties
}
}
4.测试
def main(args: Array[String]): Unit = {
hdfsPath = args(0)
proPath = args(1)
//不过滤读取
val dim_sys_city_dict: DataFrame = readMysqlTable(sqlContext, "TestMysqlTble1", proPath)
saveAsFileAbsPath(dim_sys_city_dict, hdfsPath + "TestSaveFile", "|", SaveMode.Overwrite)
}
5.执行命令
nohup spark-submit --master yarn \
--driver-memory 4G \
--num-executors 2 \
--executor-cores 4 \
--executor-memory 8G \
--class com.iptv.job.basedata.TestSaveFile \
--jars /var/lib/hadoop-hdfs/tmp_lillcol/mysql-connector-java-5.1.38.jar \
test.jar \
hdfs://ns1/user/hive/../ \
/var/.../job.properties > ./TestSaveFile.log 2>&1 &
6.运行结果
[hdfs@iptve4e03 tmp_lillcol]$ hadoop fs -du -h hdfs://ns1/user/hive/warehouse/TestSaveFile
0 0 hdfs://ns1/user/hive/warehouse/TestSaveFile/_SUCCESS
4.1 K 4.1 K hdfs://ns1/user/hive/warehouse/TestSaveFile/part-r-123412340-ec83e1f1-4bd9-4b4a-89a3-8489c1f908dc [hdfs@iptve4e03 tmp_lillcol]$ hadoop fs -cat hdfs://ns1/user/hive/warehouse/TestSaveFile/part-r-123412340-ec83e1f1-4bd9-4b4a-89a3-8489c1f908dc
1234|12349|张三|韩服_G|11234|张三艾欧尼亚|韩服-G|1234D5A3434|3|张三天庭
12343|1234|1234|韩服_M|31234|李四艾欧尼亚|韩服-M|5F4EE4345|8|1234天庭
1234|12340|石中剑山|韩服_s8|11234|张三艾欧尼亚|韩服-s8|59B403434|5|石中剑山天庭
12344|12344|灵山|韩服_J|31234|李四艾欧尼亚|韩服-J|CF19F434B|40|灵山天庭
1234|1234|他家|韩服_H|11234|张三艾欧尼亚|韩服-Z|51234EB1434|9|他家天庭
12345|12340|云浮|韩服_F|31234|李四艾欧尼亚|韩服-Y|9C9C04344|41|浮天庭
1234|12348|潮边疆|韩服_Z|41234|佛山艾欧尼亚|韩服-Z|5B034340F|15|边疆天庭
12340|12344|河姆渡人源|韩服_HY|41234|深圳艾欧尼亚|韩服-HY434123490808|18|河姆渡人源天庭
1234|1234|佛山|韩服_S|41234|佛山艾欧尼亚|韩服-FS|EEA981434|4|佛祖天庭
12340|12343|揭阳|韩服_J|41234|深圳艾欧尼亚|韩服-JY|9FF084349|10|天庭
1234|1234|石中剑边疆|韩服_|41234|佛山艾欧尼亚|韩服-HZ|440A434FC|0|石中剑边疆天庭
12348|1234|梅边疆|韩服_Z|41234|深圳艾欧尼亚|韩服-MZ|E9B434F09|14|梅边疆天庭
1234|12348|石中剑名|韩服_M|41234|佛山艾欧尼亚|韩服-MM|5D0A94434|14|石中剑名天庭
12349|1234|日本|韩服_|41234|深圳艾欧尼亚|韩服-SG|BD0F34349|19|日本天庭
1234|1234|石中剑石中剑|韩服_ST|41234|佛山艾欧尼亚|韩服-ST|18D0D0434|0|石中剑石中剑天庭
12340|1234|深圳|韩服_Z|41234|深圳艾欧尼亚|韩服-Z|31E4C4344|4|深天庭
12340|12340|石中剑尾|韩服_SW|41234|佛山艾欧尼亚|韩服-SW|1BA1234434B|10|石中剑尾天庭
12341|1234|美国|韩服_Z|41234|深圳艾欧尼亚|韩服-Q|3C09D434B|13|美国天庭
12341|1234|湛江|韩服_Z|41234|佛山艾欧尼亚|韩服-Z|3A49A4340|11|我家天庭
1234|12343|清诗和远方|韩服_Y|11234|张三艾欧尼亚|韩服-Y|4344E0F31|10|清诗和远方天庭
1234|41234|李四|韩服_AZ|31234|李四艾欧尼亚|韩服-Z|13F1D4344|1|李四天庭
7.总结
在整个过程中有几个需要注意的点
- 只能存一个列
/**
* Saves the content of the [[DataFrame]] in a text file at the specified path.
* The DataFrame must have only one column that is of string type.
* Each row becomes a new line in the output file. For example:
* {{{
* // Scala:
* df.write.text("/path/to/output")
*
* // Java:
* df.write().text("/path/to/output")
* }}}
*
* @since 1.6.0
*/
def text(path: String): Unit = format("text").save(path)
这段代码已经说明了一切,是的,只能保存只有一列的DataFrame.
但是比起RDD,DataFrame能够比较轻易的处理这种情况
def saveAsFileAbsPath(dataFrame: DataFrame, absSaveDir: String, splitRex: String, saveMode: SaveMode): Unit = {
dataFrame.sqlContext.sparkContext.hadoopConfiguration.set("mapred.output.compress", "false")
//为了方便观看结果去掉压缩格式
val allClumnName: String = dataFrame.columns.mkString(",")
val result: DataFrame = dataFrame.selectExpr(s"concat_ws('$splitRex',$allClumnName) as allclumn")
result.write.mode(saveMode).text(absSaveDir)
}
上述代码中 我们通过columns.mkString(",")获取 dataFrame 的所有列名并用","分隔,然后通过selectExpr(s"concat_ws('$splitRex',$allClumnName) as allclumn")将所有数据拼接当成一列,完美解决只能保存一列的问题
- DataFrame 某个字段为空
如果 DataFrame 中某个字段为null,那么在你最中生成的文件中不会有该字段,所以,如果对结果字段的个数有要求的,最好在数据处理的时候将有可能为null的数据赋值空串"",特别是还有将数据load进Hive需求的,否则数据会出现错位
至此DataFrame 写文件功能实现
此文为本人工作总结,转载请标明出处!!!!!!!
Spark:DataFrame 写入文本文件的更多相关文章
- Spark DataFrame写入HBase的常用方式
Spark是目前最流行的分布式计算框架,而HBase则是在HDFS之上的列式分布式存储引擎,基于Spark做离线或者实时计算,数据结果保存在HBase中是目前很流行的做法.例如用户画像.单品画像.推荐 ...
- Spark:将DataFrame写入Mysql
Spark将DataFrame进行一些列处理后,需要将之写入mysql,下面是实现过程 1.mysql的信息 mysql的信息我保存在了外部的配置文件,这样方便后续的配置添加. //配置文件示例: [ ...
- [Spark][Python][DataFrame][Write]DataFrame写入的例子
[Spark][Python][DataFrame][Write]DataFrame写入的例子 $ hdfs dfs -cat people.json {"name":" ...
- spark dataframe操作集锦(提取前几行,合并,入库等)
https://blog.csdn.net/sparkexpert/article/details/51042970 spark dataframe派生于RDD类,但是提供了非常强大的数据操作功能.当 ...
- spark DataFrame 常见操作
spark dataframe派生于RDD类,但是提供了非常强大的数据操作功能.当然主要对类SQL的支持. 在实际工作中会遇到这样的情况,主要是会进行两个数据集的筛选.合并,重新入库. 首先加载数据集 ...
- spark dataframe unionall
今天本来想写一个spark dataframe unionall的demo,由于粗心报下面错误: Exception in thread "main" org.apache.spa ...
- Android 建立文件夹、生成文件并写入文本文件内容
一.首先添加权限 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">& ...
- Java基础知识强化之IO流笔记51:IO流练习之 键盘录入学生信息按照总分排序写入文本文件中的案例
1. 键盘录入学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分排序写入文本文件中 分析: A:创建学生类 B:创建集合对象 TreeSet<Student> ...
- C# 实现写入文本文件内容功能
private void write_txt(string str1, string str2, string str3) { System.DateTime currentTime = System ...
随机推荐
- Vultr新用户充值优惠 – 最多充值100美元送100美元
Vultr商家向来是搅局的,当初海外VPS商家被Linode一家独大的时候,由于VULTR商家进入市场进行相似产品的营销,使得目前我们看到海外主机商各种低价.当然这些说法也有些武断,但是肯定是有一定的 ...
- 使用Spark进行搜狗日志分析实例——列出搜索不同关键词超过10个的用户及其搜索的关键词
package sogolog import org.apache.hadoop.io.{LongWritable, Text} import org.apache.hadoop.mapred.Tex ...
- OTP&ETS
最近觉得实在是该梳理梳理erlang的框架内容了,所以整理了下. OTP(开放电信平台):并发系统平台, 特点:容错(erlang:get_stacktrace(),try-catch,trap_ex ...
- java基础知识—继承
1.不能被继承的父类成员: private成员.子类与父类不在同包,使用默认访问权限的成员.构造方法. 2.访问修饰符: 访问修饰符 本类 同包 子类 其它 ...
- APP测试报告
招标手机APP测试总结报告 作 者: 日 期: 2016-03-10 文档编号: 002 版 本: Ver 1.0 目 录 1.测试概述 1 1.1. 编写目的 1 1. ...
- 虚拟机 linux 没有分配id
输入命令 $ vim /etc/sysconfig/network-scripts/ifcfg-ens33 将ONBOOT=no改为ONBOOT=yes 输入命令 $ :wq ...
- Spine用于Timeline(NullReferenceException: Object reference not set to an instance of an object pine.Unity.Editor.AnimationReferenceAssetEditor.OnInspectorGUI ())
报错信息:Spine.Unity.Editor.AnimationReferenceAssetEditor.OnInspectorGUI () (at Assets/Extention/Spine/E ...
- ACE + TAO工程中的Messenger启动过程
1.启动NameService服务 F:\ACESource\ACE_wrappers\TAO\orbsvcs\Naming_Service>tao_cosnaming.exe -o F:\AC ...
- 使用Pillow库 创建简单验证码
使用Pillow生成简单的验证码 本想做成字体各自按随机角度倾斜, 但没有在Pillow中找到相关的方法 import randomfrom PIL import Image, ImageDraw, ...
- MongoDB知识点拾遗梳理
MongoDB数据库安装: >apt-get install mongodb 0.MongoDB状态查看.启动.停止 >/etc/init.d/mongodb status或s ...