DataSet API编程指南之Data Sources(三)

1、Data Source创建

Data Sources也就是数据来源的意思。数据源可以从文件或者Java集合中创建初始数据集。创建数据集的一般机制被抽象为InputFormat。Flink提供几种内置格式,可以从常见的文件格式创建数据集。这些文件格式在ExecutionEnvironment中都有相应的快捷创建方式。总的来说可以分为下面两大类:基于文件和基于集合两种方式。接下来,我们将对每一种Data Source创建方式进行介绍。

(1)基于文件的创建方式

  • readTextFile(path) / TextInputFormat - 按行读取文件,并将其以字符串的形式返回。
  • readTextFileWithValue(path) / TextValueInputFormat - 按行读取文件,并以StringValues的形式返回。StringValues是可变字符串。
  • readCsvFile(path) / CsvInputFormat -解析以逗号(或其他字符)分隔的字段的文件。返回tuples, case class objects, or POJOs。支持基本的java类型及其对应值作为字段类型。
  • readFileOfPrimitives(path, delimiter) / PrimitiveInputFormat - 使用给定的分隔符解析文件。文件是由新行(或者其他字符序列)分隔的原始数据类型,例如string,Integer。
  • readSequenceFile(Key, Value, path) / SequenceFileInputFormat - 创建一个JobConf ,从指定的路径读取类型为SequenceFileInputFormat、Key类和Value类的文件,并以Tuple2的形式返回它们。

(2)基于集合的创建方式(常用于学习、测试)

  • fromCollection(Iterable) - 从可迭代集合中创建数据集。从Iterable 中返回的所有元素必须是相同的类型。
  • fromCollection(Iterator) - 从迭代器中创建数据集。Class指定迭代器返回的元素的数据类型。
  • fromElements(elements: _*) - 根据给定的对象序列创建数据集。所有对象必须具有相同的类型。
  • fromParallelCollection(SplittableIterator) - 并行地从迭代器创建数据集。Class指定迭代器返回的元素的数据类型。
  • generateSequence(from, to) - 在给定区间内的数字序列创建并行数据集。

(3)使用介绍

val env  = ExecutionEnvironment.getExecutionEnvironment

// 读取本地文件
val localLines = env.readTextFile("file:///path/to/my/textfile")

// 读取HDFS文件 nnHost:nnPort
val hdfsLines = env.readTextFile("hdfs://nnHost:nnPort/path/to/my/textfile")

// 读取CSV文件,包含3个字段
val csvInput = env.readCsvFile[(Int, String, Double)]("hdfs:///the/CSV/file")

// 读取CSV文件(包含5个字段), 但是,只读取其中的两个
val csvInput = env.readCsvFile[(String, Double)](
  "hdfs:///the/CSV/file",
  includedFields = Array(0, 3)) // take the first and the fourth field

// 以Case Classes形式读取CSV文件 
case class MyCaseClass(str: String, dbl: Double)
val csvInput = env.readCsvFile[MyCaseClass](
  "hdfs:///the/CSV/file",
  includedFields = Array(0, 3)) // take the first and the fourth field

// 将具有三个字段的CSV文件读入具有相应字段的POJO (Person)
val csvInput = env.readCsvFile[Person](
  "hdfs:///the/CSV/file",
  pojoFields = Array("name", "age", "zipcode"))

// 通过给定的元素创建DataSet
val values = env.fromElements("Foo", "bar", "foobar", "fubar")

// 从序列中创建DataSet
val numbers = env.generateSequence(1, 10000000)

// 从指定的路径读取类型SequenceFileInputFormat的文件
val tuples = env.createInput(HadoopInputs.readSequenceFile(classOf[IntWritable], classOf[Text],
 "hdfs://nnHost:nnPort/path/to/file"))

2、配置CSV解析参数

Flink为CSV解析提供了许多配置选项:

  • lineDelimiter: String 指定每条记录的分隔符,默认的行分隔符是 '\n'.
  • fieldDelimiter: String 指定每条记录字段的分隔符。默认的字段分隔符是','.
  • includeFields: Array[Int] Array[Int]定义了从输入文件中读取(忽略)哪些字段。默认情况下,解析前n个字段(由types()调用中的类型数量定义,也就是readCsvFile[types()])。
  • pojoFields: Array[String] 指定映射到CSV字段的POJO字段。CSV字段的解析器将根据POJO字段的类型和顺序自动初始化。
  • parseQuotedStrings: Character 启用引用字符串解析。如果字符串字段的第一个字符是引号字符,则字符串被解析为带引号的字符串(前导或尾的空格不被修剪)。引用字符串中的字段分隔符将被忽略。如果引号字符串字段的最后一个字符不是引号字符,则引号字符串解析失败。如果启用了带引号的字符串解析,并且字段的第一个字符是非带引号的字符串,则该字符串将解析为非带引号的字符串。默认情况下,引用的字符串解析是禁用的。
  • ignoreComments: String 指定注释前缀。所有以指定注释前缀开头的行都不会被解析和忽略。默认情况下,不忽略任何行。
  • lenient: Boolean 支持宽松的解析。例如,忽略不能正确解析的行。默认情况下,宽松的解析是禁用的,无效的行会引发异常。
  • ignoreFirstLine: Boolean 配置InputFormat以忽略输入文件的第一行。默认情况下不忽略任何行。

3、递归读取输入路径下的文件

对于基于文件的输入,当输入路径是文件夹时,内层文件默认情况下是不会遍历读取的,只会读取根目录下的文件,而忽略嵌套文件夹下的文件。可以通过配置recursive.file.enumeration参数,递归遍历嵌套文件夹下的文件。

// enable recursive enumeration of nested input files
val env  = ExecutionEnvironment.getExecutionEnvironment

// create a configuration object
val parameters = new Configuration

// set the recursive enumeration parameter
parameters.setBoolean("recursive.file.enumeration", true)

// pass the configuration to the data source
env.readTextFile("file:///path/with.nested/files").withParameters(parameters)

4、读取压缩文件内容

如果压缩文件使用适当的文件扩展名进行标记,Flink目前支持对输入文件的透明解压。尤其是,不需要对输入格式做进一步的配置,并且任何FileInputFormat 支持压缩,包括自定义输入格式。注意,压缩文件可能不会并行读取,从而影响作业的可伸缩性。

下表列出了当前flink支持的压缩方法。

压缩方法 文件后缀 可并行
DEFLATE .deflate no
GZip .gz, .gzip no
Bzip2 .bz2 no
XZ .xz no

因此,不论是压缩的文件还是普通的文件,都可以通过基于文件的方法读取数据,从而创建DataSet。压缩在实际生产中,是较为常用的措施,尤其是在大数据应用中。压缩能够带来空间的节省,磁盘IO,网络传输IO的性能提升。但是压缩文件是需要耗费CPU资源的。

猜你喜欢

转载自blog.csdn.net/kaizuidebanli/article/details/106665515