一、DataStream 和 DataSet
Flink用DataStream 表示無界數據集,用DataSet表示有界數據集,前者用於流處理應用程序,後者用於批處理應用程序。從操作形式上看,DataStream 和 DataSet 與集合 Collection 有些相似,但兩者有着本質的區別:
(1)DataStream 和 DataSet 是不可變的數據集合,因此不可以想操作集合那樣增加或者刪除 DataStream 和 DataSet 中的元素,也不可以通過諸如下標等方式訪問某個元素。
(2)Flink 應用程序通過 Source 創建 DataStream 對象和 DataSet 對象,通過轉換操作產生新的 DataStream 對象和 DataSet 對象。
運行時是應用程序被調度執行時的上下文環境,通過StreamExecutionEnvironment或ExecutionEnvironment方法會根據當前環境自動選擇本地或者集羣運行時環境。
flink在批處理中常見的source主要有兩大類。
1.基於本地集合的source(Collection-based-source)
2.基於文件的source(File-based-source)
在flink最常見的創建DataSet方式有三種。
1.使用env.fromElements(),這種方式也支持Tuple,自定義對象等複合形式。
2.使用env.fromCollection(),這種方式支持多種Collection的具體類型
3.使用env.generateSequence()方法創建基於Sequence的DataSet
1、基於本地集合的
package datasetapi.sources
import org.apache.flink.api.scala.ExecutionEnvironment
import scala.collection.mutable
import scala.collection.mutable.{ArrayBuffer, ListBuffer}
/**
* \* Created with IntelliJ IDEA.
* \* User: sunxianpeng
* \* Date: 2019/10/23
* \* Time: 20:04
* \* To change this template use File | Settings | File Templates.
* \* Description:
* \*/
object SourceTest {
import org.apache.flink.api.scala.extensions._
import org.apache.flink.api.scala._
import org.apache.flink.streaming.api.scala.extensions._
def main(args: Array[String]): Unit = {
val env = ExecutionEnvironment.getExecutionEnvironment
//0.用element創建DataSet(fromElements)
val ds0: DataSet[String] = env.fromElements("spark", "flink")
ds0.print()
//1.用Tuple創建DataSet(fromElements)
val ds1: DataSet[(Int, String)] = env.fromElements((1, "spark"), (2, "flink"))
ds1.print()
//2.用Array創建DataSet
val ds2: DataSet[String] = env.fromCollection(Array("spark", "flink"))
ds2.print()
//3.用ArrayBuffer創建DataSet
val ds3: DataSet[String] = env.fromCollection(ArrayBuffer("spark", "flink"))
ds3.print()
//4.用List創建DataSet
val ds4: DataSet[String] = env.fromCollection(List("spark", "flink"))
ds4.print()
//5.用List創建DataSet
val ds5: DataSet[String] = env.fromCollection(ListBuffer("spark", "flink"))
ds5.print()
//6.用Vector創建DataSet
val ds6: DataSet[String] = env.fromCollection(Vector("spark", "flink"))
ds6.print()
//7.用Queue創建DataSet
val ds7: DataSet[String] = env.fromCollection(mutable.Queue("spark", "flink"))
ds7.print()
//8.用Stack創建DataSet
val ds8: DataSet[String] = env.fromCollection(mutable.Stack("spark", "flink"))
ds8.print()
//9.用Stream創建DataSet(Stream相當於lazy List,避免在中間過程中生成不必要的集合)
val ds9: DataSet[String] = env.fromCollection(Stream("spark", "flink"))
ds9.print()
//10.用Seq創建DataSet
val ds10: DataSet[String] = env.fromCollection(Seq("spark", "flink"))
ds10.print()
//11.用Set創建DataSet
val ds11: DataSet[String] = env.fromCollection(Set("spark", "flink"))
ds11.print()
//12.用Iterable創建DataSet
val ds12: DataSet[String] = env.fromCollection(Iterable("spark", "flink"))
ds12.print()
//13.用ArraySeq創建DataSet
val ds13: DataSet[String] = env.fromCollection(mutable.ArraySeq("spark", "flink"))
ds13.print()
//14.用ArrayStack創建DataSet
val ds14: DataSet[String] = env.fromCollection(mutable.ArrayStack("spark", "flink"))
ds14.print()
//15.用Map創建DataSet
val ds15: DataSet[(Int, String)] = env.fromCollection(Map(1 -> "spark", 2 -> "flink"))
ds15.print()
//16.用Range創建DataSet
val ds16: DataSet[Int] = env.fromCollection(Range(1, 9))
ds16.print()
//17.用fromElements創建DataSet
val ds17: DataSet[Long] = env.generateSequence(1,9)
ds17.print()
}
}
二、基於文件的source(File-based-source)
(1):讀取本地文件
//TODO 使用readTextFile讀取本地文件
//TODO 初始化環境
val environment: ExecutionEnvironment = ExecutionEnvironment.getExecutionEnvironment
//TODO 加載數據
val datas: DataSet[String] = environment.readTextFile("data.txt")
//TODO 指定數據的轉化
val flatmap_data: DataSet[String] = datas.flatMap(line => line.split("\\W+"))
val tuple_data: DataSet[(String, Int)] = flatmap_data.map(line => (line , 1))
val groupData: GroupedDataSet[(String, Int)] = tuple_data.groupBy(line => line._1)
val result: DataSet[(String, Int)] = groupData.reduce((x, y) => (x._1 , x._2+y._2))
result.print()
(2):讀取hdfs數據
//TODO readTextFile讀取hdfs數據
//todo 初始化環境
val environment: ExecutionEnvironment = ExecutionEnvironment.getExecutionEnvironment
//TODO 加載數據
val file: DataSet[String] = environment.readTextFile("hdfs://hadoop01:9000/README.txt")
val flatData: DataSet[String] = file.flatMap(line => line.split("\\W+"))
val map_data: DataSet[(String, Int)] = flatData.map(line => (line , 1))
val groupdata: GroupedDataSet[(String, Int)] = map_data.groupBy(line => line._1)
val result_data: DataSet[(String, Int)] = groupdata.reduce((x, y) => (x._1 , x._2+y._2))
result_data.print()
(3):讀取CSV數據
//TODO 讀取csv數據
val environment: ExecutionEnvironment = ExecutionEnvironment.getExecutionEnvironment
val path = "data2.csv"
val ds3 = environment.readCsvFile[(String, String, String, String,String,Int,Int,Int)](
filePath = path,
lineDelimiter = "\n",
fieldDelimiter = ",",
lenient = false,
ignoreFirstLine = true,
includedFields = Array(0, 1, 2, 3 , 4 , 5 , 6 , 7))
val first = ds3.groupBy(0 , 1).first(50)
first.print()
三、基於文件的source(遍歷目錄)
flink支持對一個文件目錄內的所有文件,包括所有子目錄中的所有文件的遍歷訪問方式。
對於從文件中讀取數據,當讀取的數個文件夾的時候,嵌套的文件默認是不會被讀取的,只會讀取第一個文件,其他的都會被忽略。所以我們需要使用 recursive.file.enumeration 進行遞歸讀取
val env = ExecutionEnvironment.getExecutionEnvironment
val parameters = new Configuration
// recursive.file.enumeration 開啓遞歸
parameters.setBoolean("recursive.file.enumeration", true)
val ds1 = env.readTextFile("test").withParameters(parameters)
ds1.print()
四、讀取壓縮文件
對於以下壓縮類型,不需要指定任何額外的 inputformat 方法,flink可以自動識別並且解壓。但是,壓縮文件可能不會並行讀取,可能是順序讀取的,這樣可能會影響作業的可伸縮性。
//TODO 讀取壓縮文件
val env = ExecutionEnvironment.getExecutionEnvironment
val file = env.readTextFile("test/data1/zookeeper.out.gz").print()
tar -czvf ***.tar.gz