一.引言
离线日志通常使用 dt,hour,min 或者使用 timeStamp 作为累计文件的命名方式,对于文件日志中不包含时间戳或者时间信息的日志内容,为了获取其对应创建时间与文件属性,需要读取文件时同时获取其 File 对应的 FileSplit 类。
二.实践
1.思路
A. sc.newAPIHadoopFile 读取输入获得 RDD[(LongWritable, Text)]
B. asInstanceOf 转换为 NewHadoopRDD[LongWritable, Text]
C. NewHadoopRDD 支持 mapPartitionWithInputSplit ,按照输入的文件进行分区处理文件
D. inputSplit 转化为 FileSplit,既可以通过 getPath 得到路径从而解析出文件对应的时间分区
2.实现
import ArgsParseUtil
import org.apache.hadoop.io.{LongWritable, Text}
import org.apache.hadoop.mapreduce.InputSplit
import org.apache.hadoop.mapreduce.lib.input.{FileSplit, TextInputFormat}
import org.apache.spark.rdd.NewHadoopRDD
import org.apache.spark.{SparkConf, SparkContext}
object TextFileWIthSplit {
def main(args: Array[String]): Unit = {
val (argsList, argsMap) = ArgsParseUtil.parseArgs(args)
val local = argsMap.getOrElse("local", "true").toBoolean // 是否是本地模式
// 1.配置Spark
val input = argsMap.getOrElse("input", "")
val output = argsMap.getOrElse("output", "")
val conf = {
if (local)
new SparkConf().setAppName("TextFileWIthSplit").setMaster("local[1]")
else
new SparkConf().setAppName("TextFileWIthSplit")
}
// 2.spark初始化
val sc = new SparkContext(conf)
// 3.读取FileRDD
val fileRDD = sc.newAPIHadoopFile[LongWritable, Text, TextInputFormat](input)
val hadoopRDD = fileRDD.asInstanceOf[NewHadoopRDD[LongWritable, Text]]
hadoopRDD.mapPartitionsWithInputSplit((inputSplit: InputSplit, iterator: Iterator[(LongWritable, Text)]) => {
val file = inputSplit.asInstanceOf[FileSplit]
val path = file.getPath.toString
iterator.map(line => {
path + "\t" + line
})
}).saveAsTextFile(output)
}
}
假设 user 目录下存在 test_path 文件且文件中包含5个数字,则执行上述代码获取如下结果:
viewfs://c9/user/test_path 1
viewfs://c9/user/test_path 2
viewfs://c9/user/test_path 3
viewfs://c9/user/test_path 4
viewfs://c9/user/test_path 5