在Spark中读写文本文件很容易。当我们将一个文本文件读取为RDD时,输入的每一行都会成为RDD的一个元素。也可以将多个完整的文本文件一次性读取为一个pairRDD,其中键是文件名,值是文件内容。
1、读取文本文件
只需要使用文件路径作为参数调用SparkContext中的textFile()函数,就可以读取一个文本文件,如下例。如果要控制分区数的话,可以指定minPartitions。
JavaRDD<String> input = sc.textFile("file:///home/holden/repos/spark/README.md");
如果多个输入文件以一个包含数据所有部分的目录的形式出现,可以用两种方式来处理。可以仍使用textFile函数,传递目录作为参数,这样它会把各部分都读取到RDD中。有时候有必要知道数据的各部分分别来自哪个文件(比如将键放在文件名中的时间数据),有时候则希望同时处理整个文件。如果文件足够小,那么可以使用SparkContext.wholeTextFiles()方法,该方法会返回一个pairRDD,其中键是输入文件的文件名。
wholeTextFiles()在每个文件表示一个特定时间段内的数据时非常有用。如果有表示不同阶段销售数据的文件,则可以很容易地求出每个阶段地平均值。
val input = sc.wholeTextFiles("file://home/holden/salesFiles")
val result = input.mapValues{y =>
val nums = y.split(" ").map(x => x.toDouble)
nums.sum / nums.size.toDouble
}
咱啥也不说了,Java的实现复杂,且性能不如scala。我也很无奈,我也不敢问。。。
2、保存文本文件
输出文本文件也相当简单。下例演示的saveAsTextFile()方法接收一个路径,并将RDD中的内容都输入到路径对应的文件中。Spark将传入的路径作为目录对待,会在那个目录下输出多个文件。这样,Spark就可以从多个节点上并行输出了。在这个方法中,我们不能控制数据的哪一部分输出到哪个文件中,不过有些输出格式支持控制。
/**
* @author DKing
* @description
* @date 2019/6/16
*/
public class TextFileTest {
public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local").setAppName("TextFile");
JavaSparkContext sc = new JavaSparkContext(conf);
JavaRDD<String> lines = sc.textFile("");
lines.saveAsTextFile("");
}
}