IO 原理
IO 流主要分为字节流和字符流。
- 字节流可以处理任何类型的数据,如图片,视频等。
- 字符流只能处理字符类型的数据。
字节文件操作流
InputStream inputStream = new FileInputStream("path");
int i = 0;
// 一次读取一个字节
while ((i = inputStream.read()) != -1) {
// 字符在底层存储的时候存储的是数值,即字符对应的 ASCII 码。
System.out.println(i);
}
// 关闭IO流
inputStream.close();
-
字节文件输入流
FileInputStream
从path
下读取数据。 -
每次读取一个字节,然后马上打印,再接着读取下一个字节数据。
字节缓冲流(高效流)
// BufferedInputStream 字节缓冲输入流,提高了读取效率。
InputStream in = new FileInputStream("path");
// 字节缓存流
BufferedInputStream bis = new BufferedInputStream(in);
byte[] bs = new byte[20];
int len = 0;
while ((len = bis.read(bs)) != -1) {
System.out.print(new String(bs, 0, len));
}
// 关闭流
bis.close();
- 字节文件输入流
FileInputStream
从path
下读取数据。 - 读取的字节不会马上输出到控制台,而是在
BufferedInputStream
字节缓冲流的缓冲区中缓冲,接着继续读取下一个字节文本数据。 - 当缓冲区中的数据超过阈值的时候开始将缓冲区的数据全部打印在控制台。
字符缓冲流(高效流)
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("path"), "UTF-8"));
String str;
// 一次性读取一行
while ((str = reader.readLine()) != null) {
System.out.println(str);
}
// 关闭流
reader.close();
- 字节文件输入流
FileInputStream
从path
下读取数据。 - 读取的字节数据放在
InputStreamReader
的缓冲区中,接着读取下一个字节数据。 - 当
InputStreamReader
的缓冲区数据足够凑成一个字符(三个字节)时,将字节转换为一个字符传入到BufferedReader
的缓冲区缓冲。 - 当
BufferedReader
的缓冲区的字符数据达到阈值时开始将字符缓冲区的字符全部打印。
WordCount 原理
val sparkConf = new SparkConf().setMaster("local").setAppName("wordCount")
val sc = new SparkContext(sparkConf)
val lines: RDD[String] = sc.textFile("datas")
val words: RDD[String] = lines.flatMap(_.split(" "))
val wordToOne: RDD[(String, Int)] = words.map(word => (word, 1))
val wordToSum: RDD[(String, Int)] = wordToOne.reduceByKey(_ + _)
val tuples: Array[(String, Int)] = wordToSum.collect()
tuples.foreach(println)
sc.stop()
textFile
一行一行地读取文本数据,组成HadoopRDD
数据集。flatMap
对HadoopRDD
数据进行扁平化,组成MapPartitionsRDD
数据集。map
对MapPartitionsRDD
数据转化成(word,1)
结构,组成新的MapPartitionsRDD
数据集。reduceByKey
对新的MapPartitionsRDD
数据按key
进行聚合得到最终结果。
总结
- RDD 的数据处理方式类似于 IO 流,也有装饰者设计模式。
- RDD 的数据只有在调用
collect
方法时,才会真正的执行业务逻辑操作,而之前的封装全部是功能的扩展。 - RDD 不保存数据,但 IO 可以临时保存一部分数据(缓冲)。