软件安装:oracle vm virtual
插件安装:Vscode中Markdown插件下载:Markdown All in One、Markdown Preview Enhanced(为了使视图看起来比较舒服),Markdown Image(为了使插入截图更加方便)
下载好之后,打开VirtualBox,点击“新建”,按如下图填入内容:
分别对系统、存储和网络进行修改
系统内存大小可以设置的大一点,此处设置成4096MB
处理器栏可以多设置几个处理器,比如:两个或者两个以上
存储处的控制器下载并选择老师ftp上的iso文件就好了
网络的话如果为学校的电脑就使用“桥接网络”,如果是自己的电脑,选择NAT网络连接方式
设置好之后就可以启动了
打开虚拟机后,打开终端,输入 ping 网址,比如:ping www.baidu.com,如果显示如下:
则网络连接成功,虚拟机初步安装成功。
在virtualbox菜单->设备-> 安装增强功能
若安装出错,应为没有gcc的build工具,要先安装build工具:sudo apt install build-essential
安装完成后,再安装增强功能,需要手动启动安装,在安装目录下打开终端,执行:./autorun.sh
安装增强功能后,可以设置剪切板共享和文件共享,而且显示页面也可以自动调整。
安装vim编辑器:sudo apt install vim
vi有三种模式:命令、底行命令、编辑。
进入时是命令模式,可以执行命令,例如:按i可以进入编辑模式;编辑模式下按esc键进入命令模式;在命令模式下按:键进入底行命令。
临时修改:hostname 计算机名
永久修改命令:vim /etc/hostname,将文件内容改成计算机名,重启生效。
修改是为了:hadoop集群中需要计算机名与域名一致。
下载java,解压缩(可以双击解压缩)。
命令:tar-xxvf 压缩包名
验证软件可用性:在该java解压目录下执行 用cd跳转到该目录,执行./java -version,如果可以显示java的版本说明正常。
路径配置在 .bashrc 中。编辑 .bashrc: hadoop集群需要JAVA_HOME变量,在文件末尾添加
slave节点使用ubantu的server版,目的是减少系统消耗。
使用桥接网络
由于实验室不能为每台虚拟机提供一个ip地址,所以使用NAT模式
集群中的计算机必须使用固定的ip,首先需要设置NAT网络地址
点击“全局设定”,找到网络设置,点击右侧加号“+”。添加新的NAT网络:进入编辑页面:
注意界面网络地址。
注意区分启动前和启动后看是否可以上网
首先选择Spark版本,访问http://spark.apache.org进入download
选择版本3.1.2,对应hadoop版本是3.2
java版本:java8
安装方式:Java、spark、hadoop采用下载二进制压缩包、解压缩、配置环境变量方式。
其他软件使用apt安装
要求域名与计算机名相同。
实例集群需要三个节点:一个namenode、两个datanode。
域名(计算机名使用):master、slave0、slave1,可以不使用这三个,但要与配置文件对应
单干:将三个计算机修改为master、slave0、slave1。并设置固定的ip地址。永久修改计算机名 命令:sudo vim/etc/hostname
将hostname中的内容修改为需要的计算机名
域名文件 /etc/hosts
命令:sudo vim /ect/hosts
将域名写入文件
安装ssh客户端和server端软件:
命令:sudo apt install openssh-client ,
sudo apt install openssh-server
检查ssh联通情况
ssh免密配置
1)产生密钥;2)传送密钥到集群所有节点。
从master节点开始:
2)产生密钥,命令:ssh-keygen -t rsa
提示:一路回车到最后,
3)传送密钥到集群所有节点:
ssh-copy-id master
ssh-copy-id slave0
ssh-copy-id slave1
采用当前下载的jdk包配置路径方式,检查java能否正常运行
采用下载二进制包配置路径方式安装。
解压缩: tar -zxvf hadoop-3.2.2.tar.gz 或者 直接双击解压缩
解压缩后验证软件的运行:
配置路径:编辑 .bashrc,添加路径(PATH)
配置之前:
配置中完成:
配置文件路径:/home/bigdata3/桌面/hadoop-3.2.2/etc/hadoop
namenode节点当前域名是master,datanode节点当前域名是slave 0、slave1
目前配置的路径有(我此时虚拟机设置为中文版,所以路径中有中文):
export JAVA_HOME=/主目录/bigdata3/桌面/jdk1.8
export PATH=/主目录/bigdata3/桌面/jdk1.8/bin:$PATH
export HADOOP_HOME=/主目录/bigdata3/桌面/hadoop-3.2.2
export PATH=/主目录/bigdata3/桌面/hadoop-3.2.2/sbin:/主目录/bigdata3/桌面/hadoop-3.2.2/bin:$PATH
datanode节点配置文件works
datanode节点的配置的域名,一般是一个域名一行。
配置内容:
配置java根目录,确保hadoop能找到Java,
配置pid目录:
本文件中最主要的第一个配置,说明集群资源使用yarn
hdfs格式化只能进行一次,格式化时如果发现有原来的数据存在,将进入安全模式,以保护现有数据。格式化前,检查是否有数据:按照配置文件core-site.xml,检查是否存在相应目录,如果存在,决定是否格式化,如果继续格式化,需要删除节点。
hdfs格式化只能在namenode节点上进行。
命令:hadoop namenode -format
在namenode上执行命令:start-all.sh
首先检查jps进程:
检查web页面:
注意:远程集群的使用(如果自己的集群没有启动就使用老师的远程集群)
本地不配置直接使用:需要hdfs的完整URI:hdfs://namenode:port/路径
例如:hadoop fs -mkdir hdfs:172.21.5.156:9000/200110900406
我的ip:192.168.3.108 用命令行查看:
发挥部分:ip地址可能会出现被其它同学占用或者ip用尽的情况,导致虚拟机无法上网,重新设置一个没有人用的ip就可以了
将远程namenode的ip地址,写入本地hosts文件,使用时不需要“hdfs://namenode:port/路径”这部分:
安全模式是数据保全模式,不允许进入下一步操作,当集群发现数据校验有问题时进入。(生产环境下的严重问题,当前是教学环境)处理方式的退出安全模式停止集群,删除数据文件夹,namenode格式化,再启动集群就可。
丢节点知,刚启动时有,启动一阵子就没有了,引起原因有如下:
a.网络情况差
b.配置文件有问题
c.计算机速度与namenode节点比太慢了
1)文件副本问题:
hdfs是分布式存储,文件默认的block是128MB,原因是大数据环境下,每个文件都很大,要把块分的大一些,提高速度
修改文件副本的方式:修改主机的hadoop配置文件hdfs-site.xml
在values的地方修改节点数,如下:
2)数据存储位置问题
a) namenode不保存具体数据,保持的是数据信息,主要存储目录:
b)datanode :
1)-mkdir
在hdfs上创建文件夹
2)-ls
查看当前文件夹列表
3)上传文件到hdfs
-copyFromLocal,-put
用法:
hadoop fs -copyFromLocal 本地文件 /hdfs目录
hadoop fs -put 本地文件 /hdfs目录
4)-appendToFile
a.追加本地文件内容到hdfs文件中
b.追加本地文件到hdfs文件中
测试:先上传一个文件到hdfs
ab.txt内容
验证hdfs上ab.txt追加之后的内容:hadoop fs -cat /路径/文件名
追加hdfs文件到hdfs文件中(问号表示不可以,只能从本地文件追加)
6)-cat
显示hdfs文件内容
7)从hdfs拷贝文件到本地
第一种:-copyToLocal
第二种:-get
拷贝一个文件到本地
不改名拷贝不需要写aFromhdfs.txt 拷贝一个文件夹到本地
8)-cp是hdfs上的拷贝
a.文件拷贝
原文件
执行拷贝命令 hadoop fs -cp /200110900406/b.txt /200110900406/b2.txt
拷贝成功:
b.目录拷贝
原目录:
执行命令:
hadoop fs -cp /200110900406/ /200110900406_2
拷贝成功:
9)-df:显示文件hdfs文件系统信息
10)-mkdir:创建目录
11)文件移动
a.本地文件移动到hdfs:-moveFromLocal
b.hdfs移动到本地:-moveToLocal
c.hdfs上的移动:-mv,linux下无改名字这个命令
原目录:
执行命令:hadoop fs -mv /200110900406_2 /200110900406_3
修改成功
12)-rmdir
不能删除非空目录。如果要删除非空目录,需要带参数 --ignore-fail-on-non-empty,错误不显示,但是删不了非空目录,可以创建一个新空目录再删除
为什么删不掉:对数据的目录而言,数据相对安全
12)-rm:删除文件或目录(需要带 -r/-R)都可以
删除文件:
执行命令:hadoop fs -rm /200110900406/b.txt
删除成功:
删除目录:
原目录
执行命令:hadoop fs -rm -r /200110900406_3
删除成功:
注意:对非空目录删除不提示,对数据安全是不利的,建议删除文件用-rm,删除目录用-rmdir
13)-touch:在hdfs上建立文件
采用下载二进制软件包,解压缩,配置环境变量的方式。
双击解压缩:scala-2.12.15
验证:进入scala目录下的bin目录,执行:./scala
配置环境变量:vim ./bashrc
配置好后可直接运行scala
a.一定要使用var或者val
注:其中var是可变的,val是不可变的
如果不指定数据类型,系统会自动识别。
指定数据类型的方式: val(var) 变量名:数据类型
注:首字母大写
String类型是默认导入的java.lang包的内容,可直接使用
与其它语言相同
位运算符:计算结果是数字(一般是Int)
位运算与布尔值不可以直接运算
scala每个语句块都有返回值,返回值是最后一个可执行语句的值。一般不需要用return明确指定。
idea安装:下载二进制软件包,解压缩,配置路径
编辑.bashrc,将.bashrc.sh路径添加到PATH
首先创建一个新项目
选scala语言,用IDEA进行包管理(手工包管理):
给项目起名字,检查 scala SDK和JDK是否正确,然后点击“Finish”
按流程建立main程序。
左侧选中src,菜单File->New->Package
给包取个名字
一定要选“Object”,对于main所在的对象而言,是一个单例对象
val resultIf={if(c1>c2) "c1>c2" else "c1<=c2"}
for(变量<-集合){
循环体
}
for也可用于赋值语句。需要使用yield,允许在for循环内进行计算:
if语句
方式一:
if(布尔表达式) x else y
方式二:
if(布尔表达式){
.......
}esle{
......
}
while循环与do while循环
与其他语言使用方法相同
break 和continue
与其他语言不通,在普通循环for、while、do while中一般不可以使用 。在scala语言中一般用守卫(用if语句来实现断句)来实现
scala的集合数据类型
1.数组:默认为定长数组
2.使用可变数组需要导入相应的包
3.遍历数组的编程:
a.使用数组的index
b.直接遍历
Map
Map映射是键值对的集合
(“age”->19)+(“age”->24)=(“age”->43)
注意:只有键相同的才可以相加,并且返回值相加的结果
元组
用圆括号()包裹数据,数据类型可以不同
元组中数据的访问形式:
元组名字._index
元组的嵌套访问(元组内的元组的数据):
列表
集合set的特点是:不包括重复的元素
发挥部分:Trait特性
Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大,与接口不同的是,它还可以定义属性和方法的实现。抽象类和接口的结合,一般情况下Scala的类可以继承多个Trait,从结果来看就是实现了多重继承。Trait的继承用exten关键字继承,多继承时多个Trait之间用with连接,Trait(特征) 定义的方式与类类似,但它使用的关键字是 trait,继承的多个trait中如果有同名的方法和属性,必须要在类中使用“override”重新定义,trait中不可以传参数。
代码:
trait Read {
val readType = "Read"
val gender = "m"
def read(name:String){
println(name+" is reading")
}
}
trait Listen {
val listenType = "Listen"
val gender = "m"
def listen(name:String){
println(name + " is listenning")
}
}
class Person() extends Read with Listen{
override val gender = "f"
}
object test {
def main(args: Array[String]): Unit = {
val person = new Person()
person.read("zhangsan")
person.listen("lisi")
println(person.listenType)
println(person.readType)
println(person.gender)
}
}
(1)函数的定义:
def 函数名(参数列表):返回值 ={函数体},如果系统可以自动判断出来,可以不写
参数格式: 参数名:类型;如果定义默认参数,直接赋值。标准的用法是,带默认的形参放在默认参数后面。默认参数可以在任意位置,但如果默认参数后有非默认参数,调用时必须带形参名
(2)匿名形式定义
参数表=>{函数体}
匿名形式定义也可以有名字,将函数赋值给一个变量就可以,例如:
val 变量名=(参数表)=>{函数体}
(3)高阶函数
高阶函数定义:参数里有函数或返回值是函数
a.参数里有函数
例题:用已定义函数abc完成四则运算
b.用匿名函数完成四则运算:
当作为函数参数的函数只用一次且书写长度比较短时,一般直接在调用时使用匿名函数
c.函数返回值是函数
例如:用函数返回值是函数的函数计算加减法:(代码如下)
def abc(x:Int):(Int,Int)=>{
if(x>5)(b:Int,a:Int)=>b+a else (b:Int,a:Int)=>b-a
}
val aa=abc(1)
printLn(aa(4,5))
val bb=abc(10)
printLn(bb(4,5))
采用下载二进制软件包,解压缩,配置环境变量的方式。spark是计算框架,集群运行环境可以是hadoop,也可以是spark(生产环境不常用,因为没有分布式文件系统)
双击解压缩:spark-3.1.2-bin-hadoop3.2.tgz
验证:进入spark目录bin下,执行:./spark-shell
配置环境变量路径PATH:编辑vim .bashrc,添加SPARK_HOME,SCALA_HOME
RDD的操作是惰性的,RDD的操作分成两大类:转换类和执行类。
转换类:转换类的操作都是惰性的,只有遇到执行类操作时才执行,之前只是记录操作过程,不执行。
RDD可以执行链式操作,每次转换操作后还是RDD。
(1)从本地文件创建
命令:sc.textFile(URI)
(2)从hdfs文件创建
命令:sc.textFile(URI)
(3)从集合数据中创建
命令:sc.parallelize()
1)新建一个scala语言项目,用IDEA进行包管理
2)添加spark库到项目中
idea菜单 File->project structure
程序:
(1)filter过滤
filter(function),按照function中的规则过滤数据
用链式写法完成以上程序:
sc.textFile(path="hdfs://192.168.3.108:9000/200110900406/ab.txt").filter(_.contains("c")).foreach(println)
(2)Map(function)
将集合中的每个数据按照function制定的规则进行处理
将_.contains(“c”)和原始数据组合到一起显示:
发挥部分:RDD是只读的,要想改变RDD中的数据,只能在现有的RDD基础上创建新的RDD;由一个RDD转换到另一个RDD,可以通过丰富的操作算子(map、filter、union、join、reduceByKey… …)实现,不再像MR那样只能写map和reduce了。
创建RDD时指定分区数的方法:textFile的第二个参数。如下程序指定最少三个分区:
val conf =new SparkConf().setAppName("hhh").setMaster("local[*]")
val sc=new SparkContext(conf)
val myRdd=sc.textFile(path = "file:///home/bigdata3/a.txt",minPartitions = 3)
val out1=myRdd.collect()
out1.foreach(println)
Thread.sleep(1000 * 60 * 5)
打开链接:http://192.168.3.108:4040
出现界面:
在进行分词时
val out1=myRdd.map(x=>x.split(" ")).collect()
out1.foreach(x=>println(x))
输出的是数据的地址而不是数据
所以需要变换输出语句为:
out1.foreach(x=>x.foreach(x=>println(x)))
或者:
out1.foreach(_.foreach(println))//高级写法
DAG图:
shuffle操作会把DAG图分成不同的stag,每个分区都有shuffle操作
![在这里插入图片描述](https://img-blog.csdnimg.cn/01add64ccf7f4b6a8aefa551f3e8f98b.png#pic_center)flatMap
代码:
执行结果:
验证map和flatMap之间有没有shuffle操作:
结果表明,map和flatMap之间灭有shuffle操作
思路分析:
(1)首先读入文件内容转换为RDD,再用flatMap进行分词,组成键值对(词,1),进行键值队的加法。
标准的写法用链式写法(一句话就行):
val myRdd=sc.textFile(path = "file:///home/bigdata3/a.txt",minPartitions = 3).flatMap(x=>x.split(" ")).map((,1)).reduceByKey(+_).foreach(x=>println(x))
(1)修改程序指定的master
将setMaster(“local[*]”)删除,通过命令指定参数运行模式
(2)文件路径不能是本地路径:
(3)spark程序在集群上的运行模式
有两种模式:
(4)提交任务的命令:spark-sunmit
打开一个终端创窗口,输入: spark-submit,查看帮助
–master MASTER_URL
集群是standalone模式搭建:spark://host:port;集群是mesos模式搭建:mesos://host:port;集群是yarn模式搭建:yarn。如果没有这个参数,将是local模式。
不同运行模式,需要对spark进行相应配置。
以yarn集群配置为例:
SPARK-CONF_DIR:spark配置文件的路径,默认:${SPARK_HOME}/conf,如果在.bashrc配置了环境变量
SPARK_HOME,使用默认默认值就可以了。
HADOOP_CONF_DIR:hadoop配置文件的路径
YARN_CONF_DIR:yarn的配置路径
–delpoy -mode
指定运行模式:client或者cluster。
–class
要运行哪个class,如果运行的是main所在的class,可以不写此参数。
–jar
运行时所需要的jar包,用逗号分割。
–packages
运行时所需要的package
–exclude-packages
解决依赖冲突的
–repositories
远程库
–files
需要放到executor工作目录下的文件
(1)修改程序
修改的每一句都建议通过spark-shell先进行验证
删除.setMaster,修改输入为hdfs:
(2)打包配置
菜单 file->project structure->artifacts,点击"+"
系统自动填入modul名字,选择main class
点击“OK”
进行jar包的瘦身,即删除不用的jar包,将除最后一个的以外的jar包全部都删除
删除后:
观察jar包名字、路径,然后点击“OK”
(3)打包
菜单->Build->Artifacts
第一次选择build,第二次选择rebuild/先clear 再build,建立完成提示:
命令: spark-submit
–master yarn
–deploy-mode client demo2.jar
运行之前要求通过本地yarn的配置,能够找到运行yarn的集群,要在hosts中写入远程集群的maste
命令:spark-submit
–master yarn
–deploy-mode client demo2.jar
在hosts中配置远程集群的master。
新建项目,程序:
在idea中输入参数:
菜单run-edit configurations:
输入了参数“123” “456”,参数之间用空格隔开,满足两个参数的条件,所以输出:
如果不满足两个参数,则控制台输出:program argument error
路径:
执行成功:
本地生成文件:out.txt文件夹
创建一个文件,并给予可执行权限。例如,创建一个文件,并输入如下:
echo spark-submit start
spark-submit --master yarn --deploy-mode cluster /home/bigdata3/IdeaProjects/11.30/out/artifacts/11_30_jar/11.30.jar "hdfs://192.168.3.89:50070/200110900406/ab.txt" "hdfs://192.168.3.89:50070/200110900406/nov"
保存文件后退出,执行:
chomd +x 文件名
sparkSunmit.sh文件内容:
执行:
评分在ratings.dat文件中,将ratings.dat读入为RDD,取出MovieId和Rating
各种数据类型:
(1)获取数据
取出文件:
val movie=sc.textFile("file:///home/bigdata3/ml-1m/ratings.dat").map(_.split("::"))
(2)求评分平均值
取出相应的数据组成键值对,Rating数值计算需要进行数据类型转换(此处使用toDouble):
查看前10个数据:movie.take(10)
组成键值对:
val movie2=movie.map(x=>(x(1),x(2))).take(10)
与1形成键值对:val movie_1=movie.map(x=>(x(1),1)).take(10)
正式求得时候,代码:(因为在take的时候会变成array里面的array,由上图所示)
进行数据类型转换并求总分:
(3)求评分的数量(每个电影有多少个评分):
(4)求电影评分平均值
思路:同一个电影的总分/总评分人数
首先,组成键值对,键:电影的MovieId,值:(总评分,评分数);
(5)取出平均分前五
(6)取出评分平均分前五的电影名
代码:
val spark = SparkSession.builder().master("local[*]").appName("sparkSQL1")
.config("spark.some.config.option", "some-value").getOrCreate()
DataFrame:导带有schame信息的RDD,数据既可以来自RDD,也可以来自Hive,HDFS等外部数据库,还可以时json格式的数据
代码:
val df = spark.read.json("/home/bigdata3/software/spark-3.1.2-bin-hadoop3.2/examples/src/main/resources/people.json")
df.show()
dataframe会显示带有格式的schema,people.json文件的内容
创建的schema属性顺序是按照字母表顺序进行排序的
(1)引入式隐式转换
当前需要将DataFrame当成是架构化数据,才能执行sql,所以需要隐式转换。注意:隐式转换的位置在sparksession入口点创建之后,如下位置:
(2)显示schema样式位置
df.printSchema()
生成DataFrame时产生了schema,schema自动识别数据类型,是根据原始数据自动识别的。
(3)DataFrame与关系数据库相同吗?
验证方式:在原始数据中写入两个完全相同的数据,对于关系数据库而言,是不可以的,观察DataFrame:
两个完全相同的数据都存在,说明与关系数据库是不同的。
(4)select语句与数据库是十分相似的
查询:
语句:
df1.select("gender").show()
df1.select("name","gender").show()
结果:
加“$”的情况,表示将变量代表的数据值取出来:
将查询数据进行计算:
df1.select("name","age"+1).show()
上面这条语句是不可以的,应该使用如下:
df1.select($"name",$"age"+1).show()
注意:“$”只是针对数值运算
(5) filter过滤,数值过滤:
df1.filter($“age”>19).show()
(6)groupBy
分组聚合:如果有计算的话,主要针对的是数值属性
注意:null也参与计算
(7)SQL查询编程
首先要创建一个临时表,然后再执行查询。
创建一个临时视图:
注意:下面的py是增强代码块的特性,指代码块是python语法,不同的markdown编辑器对此支持可能会有不同
val df2 = spark.read.json("/home/bigdata3/software/spark-3.1.2-bin-hadoop3.2/examples/src/main/resources/people3.json")
df2.createOrReplaceTempView("people2")
val sqlDF=spark.sql("select * from people2")
sqlDF.show()
结果:
部分属性的查询:
语句和sql的一样
发挥部分:
DataSet补充介绍:
1)DataSet是在Spark1.6中添加的新的接口。
2)与RDD相比,保存了更多的描述信息,概念上等同于关系型数据库中的二维表。
3)与DataFrame相比,保存了类型信息,是强类型的,提供了编译时类型检查。
4)调用Dataset的方法先会生成逻辑计划,然后Spark的优化器进行优化,最终生成物理计划,然后提交到集群中运行。
5)DataSet包含了DataFrame的功能,在Spark2.0中两者得到了统一:DataFrame表示为DataSet[Row],即DataSet的子集。
DataSet实例分析:
(1)首先要创建一个临时视图,再进行查询:
case class Person(name:String,age:Long)
object testDataSet3 {
def main(args: Array[String]): Unit = {
val spark=SparkSession.builder().master("local[*]")
.appName("testDataSet3").config("123","123").getOrCreate()
Person(name:String,age:Long)
import spark.implicits._
val caseClassDS=Seq(Person("Andy",32),Person("Tom",20)).toDS()
caseClassDS.show()
}
}
运行结果:
(2)没有定义泛型的DataSet
使用caseclass给予每组数据一个类型
case class Person(name:String,age:Long)
object testDataSet3 {
def main(args: Array[String]): Unit = {
val spark=SparkSession.builder().master("local[*]")
.appName("testDataSet3").config("123","123").getOrCreate()
import spark.implicits._
var primitiveDS=Seq(("0",1,2,3),("4",5,6,7),("7",9,8,9)).toDS().show()
}
系统按照位置自动定义泛型:
(3)Dataframe转换成DataSet
可以提供一个class将Dataframe转换为DataSet
object testDataSet3 {
def main(args: Array[String]): Unit = {
val spark=SparkSession.builder().master("local[*]")
.appName("testDataSet3").config("123","123").getOrCreate()
//case class Person(name:String,age:Long)
import spark.implicits._
val path1="/home/bigdata3/spark-3.1.2-bin-hadoop3.2/examples/src/main/resources/people.json"
spark.read.json(path1).as[Person].show()
var primitiveDS=Seq(("0",1,2,3),("4",5,6,7),("7",9,8,9)).toDS().show()
}
}
运行结果:
(4)与RDD的交互操作
通过session创建sc
val sc=spark.sparkContext
A.用反射弧添加schema
通过case class可以将RDD转化为DataFrame
object testDataSet3 {
def main(args: Array[String]): Unit = {
val spark=SparkSession.builder().master("local[*]")
.appName("testDataSet3").config("123","123").getOrCreate()
import spark.implicits._
val sc=spark.sparkContext //生成sparkContext,为读取txt文件
val path1="/home/bigdata3/spark-3.1.2-bin-hadoop3.2/examples/src/main/resources/people.txt"
val peopleDF=sc.textFile(path1)//读取文件
‘’.map(x=>x.split(","))//将数据分开
.map(x=>Person(x(0),x(1).trim.toInt))//用得到的数据生成Person对象
.toDF()//转化为Dastaframe
peopleDF.show()
peopleDF.createOrReplaceTempView("People")//生成临时视图
val pDF=spark.sql("SELECT name,age from People where age between 13 and 29")//选出数据
pDF.show()
pDF.map(x=>("name1:"+x(0))).show()
}
运行结果:
B.通过程序添加schema
如果不能通过预先定义case class,class进行到RDD到DataFrame转换,需要通过用以下三步转换成DataFrame:
代码:
object testDataSet3 {
def main(args: Array[String]): Unit = {
val spark=SparkSession.builder().master("local[*]")
.appName("testDataSet3").config("123","123").getOrCreate()
import spark.implicits._
val sc=spark.sparkContext
val path1="/home/bigdata3/spark-3.1.2-bin-hadoop3.2/examples/src/main/resources/people.txt"
val peopleRDD=sc.textFile(path1)
val schemeString = "name age"
val fields=schemeString.split(" ")
.map(x=>StructField(x,StringType,nullable = true))
val schema=StructType(fields)
val rowRDD=peopleRDD.map(_.split(","))
.map(x=>Row(x(0),x(1).trim))
val peopleDF = spark.createDataFrame(rowRDD,schema)
peopleDF.show()
}
}