程序员人生 网站导航

深入理解Java中的流---结合Hadoop进行详解

栏目:php教程时间:2016-08-01 17:49:06

在JavaSe的基础课程当中,可以说流是1个非常重要的概念,并且在Hadoop中得到了广泛的利用,本篇博客将围绕流进行深入的详解。
(1)JavaSe中流的相干概念
1、流的定义
①在Java当中,若1个类专门用于数据传输,则这个类称为流
②流就是程序和装备之间嫁接以来的1根用于数据传输的管道,这个装备可以是本地硬盘,可以是内存条,也能够是网络所关联的另外1台计算机等等,其中不同管道上有不同的按钮,按下不同的按钮相当于调用不同的方法,这根带按钮的用于数据传输的管道就是流,即流就是1根管道
这里写图片描述
③流1定是类,但类不1定是流
2、流的分类
依照数据流的方向不同分为输入流与输出流、依照处理数据单位的不同分为字节流与字符流、依照功能的不同分为原始流与包裹流。
输入流与输出流:所谓输入流就是通过输入管道从指定的装备当中读取数据,例如键盘。所谓输出流就是通过输出管道向指定的装备当中写入数据,例如显示器。
字节流与字符流:字节流处理数据的单位是1个字节,字符流处理数据的单位是1个字符,在Java当中1个字符相当于两个字节。
原始流:可以从1个特定的装备即数据 源中读写数据的流,就像是1条单1的管道接到水龙头上开始放水。
包裹流:所谓包裹流就是由于原始流的功能太简单了,对原始流进行1定的加工处理—-在原始流的基础上套1个功能比较强大的管子,这个管子称为包裹流。包裹流类似于在1条已存在的管子套上另外1根管子。
原始流与包裹流的关键区分在于能不能直接连接到装备。
3、4大基本抽象流
所谓4大基本抽象流就是4大基本抽象类,4大基本抽象流包括字节流和字符流,其中字节流包括InputStream和OutPutstream,字符流包括Reader和Writer,并且凡是以Stream结尾的都是字节流。
字节流与字符流的方法1模1样,仅仅是处理数据的单位不1样;InputStream是所有字节输入流的父类、OutputStream是所有字节输出流的父类;Reader是所有字符输入流的父类,Writer是所有字符输出流的父类。
4、IO包中经常使用的流
文件流(原始流):
FileInputStream FileReader
FileOutputStream FileWriter
输出流(原始流):
PrintStream
缓冲流(包裹流):
BufferedInputStream BufferedReader
BufferedOutputStream BufferedWriter
转换流(包裹流):
InputStreamReader
OutputStreamWriter
数据流(包裹流):
DatainputStream
DataOutputStream
5、文件流、输出流、缓冲流、转换流、数据流的相干作用
文件流:Java中的文件流可以将1个文件的内容按字节或字符为单位来进行读写、复制
输出流:PrintStream在OutputStream基础之上提供了增强的功能,可以将基本类型数据格化后的字符串进行输出
缓冲流:缓冲流就是带有缓冲区的输入输出流,带缓冲区的流比不带缓冲区的流运行速度要快,由于此时此刻不是读1个写1个,而是读取完以后先放到缓冲区里面,在1次性写到指定的装备当中
转换流:InputStreamReader的作用是将输入字节流转换成字符流
OutputStreamWriter的作用是将输出字节流转换成字符流
数据流:Java中的数据流能够以1种与机器无关的方式,直接从底层字节输入流当中读取基本类型数据或直接将基本类型数据写到字节输出流当中,即数据流可以将基本类型数据的2进制直接读入或写出
6、简述字节流与字符流的区分
1>字节流可以处理所有格式的文件,但是带有汉字的文本通过字节流输出到显示器上时会出现乱码的现象,但是若要完成的是文本文件的复制则不会出现乱码的现象—即字节流可以完成文本文件的拷贝
但是Hadoop中的IOUtils工具类解决了字节流的这个缺点
2>字符流只能处理文本格式的文件,不能处理非文本格式的文件,由于非文本格式的文件本身就不是由1个1个字符组成的,因此若要当作1个1个字符来解读肯定会出错
3>在实际项目当中字节流是广泛使用的
(2)JavaSe中流的具体利用—-结合Hadoop中的Api(IOUtils)
IOUtils是Hadoop自己提供的工具类,在编程的进程中用的非常方便———import org.apache.hadoop.io.IOUtils,下面将结合具体的实例进行说明。
实际开发进程中提倡2点:
1>尽可能用字节流处理问题
2>尽可能用Hadoop中的org.apache.hadoop.io.IOUtils工具类解决问题,由于简单
实例1:读取1个文件的内容,并将其输出到显示器上
方法①

package JavaSe; import java.io.BufferedReader; import java.io.FileReader; public class App1 { public static void main(String[] args) throws Exception { BufferedReader fr = new BufferedReader(new FileReader("C:\\file.txt")); int i = fr.read(); while(-1!=i)//⑴表示读取到了文件的末尾 { System.out.print((char)i); i = fr.read(); } } } //运行结果: /* Sometimes your plans don’t work out because God has better ones. 毅力和耐性在某种程度上将决定1个人会成为何样的人。 */

方法②

package JavaSe; import java.io.BufferedReader; import java.io.FileReader; public class App1 { public static void main(String[] args) throws Exception { BufferedReader fr = new BufferedReader(new FileReader("C:\\file.txt")); char[] buf = new char[1024]; int len = fr.read(buf);//从fr所关联的文件当中读取数据并寄存在数组buf中 System.out.println(new String(buf,0,len)); } } //运行结果: /* Sometimes your plans don’t work out because God has better ones. 毅力和耐性在某种程度上将决定1个人会成为何样的人。 */

方法③利用Hadoop自带的工具类:IOUtils(解决了字节流将汉字文本输出到显示器上时出现乱码的缺点),并且相比于JavaSe中IO的方法更简单

package JavaSe; import java.io.FileInputStream; import org.apache.hadoop.io.IOUtils; public class App1 { public static void main(String[] args) throws Exception { FileInputStream fr = new FileInputStream("C:\\file.txt"); IOUtils.copyBytes(fr,System.out,1024,true); } } //运行结果: /* Sometimes your plans don’t work out because God has better ones. 毅力和耐性在某种程度上将决定1个人会成为何样的人。 */

实例2:编程实现文件的复制—将C盘下的file.txt文本文件复制到D盘下的file2.txt文本文件中
方法①

package JavaSe; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; public class App2 { public static void main(String[] args) throws Exception { BufferedInputStream fr = new BufferedInputStream(new FileInputStream("C:\\file.txt")); BufferedOutputStream fw = new BufferedOutputStream(new FileOutputStream("D:\\file2.txt")); int i = fr.read(); while(-1!=i) { fw.write(i); i = fr.read(); } fw.flush(); fr.close(); fw.close(); } }

方法②

package JavaSe; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; public class App2 { public static void main(String[] args) throws Exception { BufferedInputStream fr = new BufferedInputStream(new FileInputStream("C:\\file.txt")); BufferedOutputStream fw = new BufferedOutputStream(new FileOutputStream("D:\\file2.txt")); byte[] buf = new byte[1024]; int i = fr.read(buf); fw.write(buf,0,i); fw.flush(); fw.close(); fr.close(); } }

方法③利用Hadoop自带的工具类:org.apache.hadoop.io.IOUtils,相比于JavaSe中IO的方法更简单

package JavaSe; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.PrintStream; import org.apache.hadoop.io.IOUtils; public class App2 { public static void main(String[] args) throws Exception { BufferedInputStream fr = new BufferedInputStream(new FileInputStream("C:\\file.txt")); System.setOut(new PrintStream("D:\\file2.txt"));//对标准输出流进行重定向 IOUtils.copyBytes(fr,System.out,1024,true); } }

实例3:利用BufferReader中的readLine()方法和BufferedWriter中的writeLine()方法完成文本文件的复制—-项目中常做这个事情

package JavaSe; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; public class App3 { public static void main(String[] args) throws Exception { BufferedReader fr = new BufferedReader(new FileReader("C:\\file.txt")); BufferedWriter fw = new BufferedWriter(new FileWriter("D:\\file2.txt")); String str = fr.readLine(); while(str!=null) { fw.write(str); fw.newLine(); str = fr.readLine(); } fw.flush(); fr.close(); fw.close(); } }

实例4:编程实现将long基本类型数据写入byte数组,然后再从byte数组中把该数据读出来—-这是Socket编程中常常要完成的任务
方法①

package JavaSe; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.util.Scanner; public class App4 { public static void main(String[] args) throws Exception { Scanner scanner = new Scanner(System.in); long i = scanner.nextLong(); ByteArrayOutputStream array = new ByteArrayOutputStream();//内核为字节数组 DataOutputStream fw = new DataOutputStream(array); fw.writeLong(i);//将长整型变量i写到字节数组中 byte[] byteArray = array.toByteArray();//拷贝array内核字节数组的内容 ByteArrayInputStream bytearray = new ByteArrayInputStream(byteArray); DataInputStream fr = new DataInputStream(bytearray); long j = fr.readLong(); System.out.println(j); } } //运行结果: /* 65 65 * */

方法②

package JavaSe; import java.util.Scanner; public class App4 { public static void main(String[] args) throws Exception { Scanner scanner = new Scanner(System.in); long i = scanner.nextLong(); String str = i +""; byte[] bytes = str.getBytes();//将长整型变量i间接存到数组中 System.out.println(new String(bytes)); } } //运行结果: /* 65 65 * */

注:本例子不合适用Hadoop自带的工具类:org.apache.hadoop.io.IOUtils进行解决
实例5:利用数据流完成1个基本类型数据序列化与反序列化的实例

package JavaSe; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.Scanner; public class App5 { public static void main(String[] args) throws Exception { Scanner scanner = new Scanner(System.in); int i = scanner.nextInt(); int j = scanner.nextInt(); DataOutputStream fw = new DataOutputStream(new FileOutputStream("C:\\file2.txt")); fw.writeInt(i); fw.writeInt(j); DataInputStream fr = new DataInputStream(new FileInputStream("C:\\file2.txt")); int i2 = fr.readInt(); int j2 = fr.readInt(); System.out.println(i); System.out.println(j); } } //运行结果: /* 65 56 65 56 * */

序列化与反序列的注意事项:
1>所谓序列化就是将对象以2进制情势写到字节输出流当中,所谓反序列化就是将对象从字节输入流当中读取出来
2>序列化与反序列化的顺序要保持相同:哪一个数据先写进流管道里,哪一个数据就先从流管道里读出来
3>Java中的数据流是将基本类型数据的2进制代码写到文本文件中,而Java中的输出流PrintStream是将基本类型数据的字符串写到文本文件中/font>
下面为示例结果:
当我们将上面程序中的file2.txt文件打开以后结果以下:
这里写图片描述
其中:
00 00 00 41为65的16进制,00 00 00 38为56的16进制
实例5:编程实现将键盘输入的字符组成字符串直接赋给String对象
方法①

package JavaSe; import java.io.BufferedReader; import java.io.InputStreamReader; public class App5 { public static void main(String[] args) throws Exception { BufferedReader fr = new BufferedReader(new InputStreamReader(System.in));//将键盘输入的字节流转化为字符流 String str = fr.readLine(); System.out.println(str); } } //运行结果: /* 数据分析玩家shujufenxiwanjia 数据分析玩家shujufenxiwanjia */

方法②

package JavaSe; import java.util.Scanner; public class App5 { public static void main(String[] args) throws Exception { Scanner scanner = new Scanner(System.in); String str = scanner.nextLine(); System.out.println(str); } } //运行结果: /* 数据分析玩家shujufenxiwanjia 数据分析玩家shujufenxiwanjia */

实例6:标准输入输出的重定向:编程实现将键盘输入的数据输入file1.txt文件中,如果输入有误,则将出错信息输出到B文件中
所用知识点:
1>相干api以下图所示:
这里写图片描述
这里写图片描述
2>Java异常中的e.printStackTrace()方法默许是将出错信息输出到System.err所关联的装备中

package JavaSe; import java.io.PrintStream; import java.util.Scanner; public class App6 { public static void main(String[] args) throws Exception { System.setOut(new PrintStream("C:\\file1.txt"));//重定向输出 System.setErr(new PrintStream("C:\\file2.txt"));//重定向毛病输出 while(true) { Scanner scanner = new Scanner(System.in); try { int i = scanner.nextInt(); System.out.println(i); } catch(Exception e) { e.printStackTrace(); } } } }

运行终了后:
file1.txt文本文件中的内容为:
23
56
file2.txt文本文件中的内容为:
java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:864)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
at JavaSe.App1.main(App1.java:19)

针对JavaSe基础编程当中流的用法就写到这里,如有问题,欢迎留言指正!

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐