IO流

 关键词:字节、字符、包装、流

整个Java IO体系都是基于字符流(InputStream/OutputStream) 和 字节流(Reader/Writer)作为基类,根据不同的数据载体或功能派生出来的。

  • 文件流:FileInputStream/FileOutputStream, FileReader/FileWriter

前者对应着字节流(byte),后者对应着字符流(char),读写都是无缓存的。

 1 public class HelloWorld {
 2 
 3     public static void main(String[] args)  {
 4         
 5             try {
 6                 FileInputStream fin = new FileInputStream("C:\\Users\\Administrator\\workspace\\test1\\src\\2.txt");
 7                 FileOutputStream fout = new FileOutputStream("C:\\Users\\Administrator\\workspace\\test1\\src\\1.txt");
 8                 byte[] buf = new byte[1024]; //分块
 9                 int len = 0;
10                 while((len=fin.read(buf))>0)
11                 {
12                     fout.write(buf,0,len);
13                     
14                 }
15             
16                 fout.close();
17             } catch (IOException e) {
18                 // TODO Auto-generated catch block
19                 e.printStackTrace();
20             }
21             
22             
23     }
24         
25 }
  • 包装流:PrintStream/PrintWriter/Scanner

PrintStream可以封装(包装)直接与文件交互的节点流对象OutputStream, 使得编程人员可以忽略设备底层的差异,进行一致的IO操作。因此这种流也称为处理流或者包装流。

PrintWriter除了可以包装字节流OutputStream之外,还能包装字符流Writer

Scanner可以包装键盘输入,方便地将键盘输入的内容转换成我们想要的数据类型。

ps:包装的意思是添加了很多的功能,使对原来流的操作更加方便

                FileOutputStream fos = new FileOutputStream("tmp.txt");
                PrintStream ps = new PrintStream(fos)) {
                ps.println("普通字符串\n");

通过传参,ps将fos包装,使用println函数就可以直接打印数据到fos对应的流里面。

  • 字符串流:StringReader/StringWriter

这两个操作的是专门操作String字符串的流,其中StringReader能从String中方便地读取数据并保存到char数组,而StringWriter则将字符串类型的数据写入到StringBuffer中(因为String不可写)。

ps:StringReader其实就是把字符串当作了输入流

 1 public class HelloWorld {
 2 
 3     public static void main(String[] args)  {
 4         
 5        
 6             String s = "qegjkljg";
 7             StringReader sr = new StringReader(s);
 8             char[] buf = new char[2];
 9             int len=0;
10             try {
11                 while((len=sr.read(buf))>0)
12                 {
13                     System.out.println(new String(buf,0,len));
14                 }
15             } catch (IOException e) {
16                 // TODO Auto-generated catch block
17                 e.printStackTrace();
18             }
19     }
20         
21 }
  • 转换流:InputStreamReader/OutputStreamReader

这两个类可以将字节流转换成字符流,被称为字节流与字符流之间的桥梁。我们经常在读取键盘输入(System.in)或网络通信的时候,需要使用这两个类

ps:这两个类需要对InputStream/OutputStream封装,而不能直接对文件进行封装

 

  • 缓冲流:BufferedReader/BufferedWriter , BufferedInputStream/BufferedOutputStream
  • 没有经过Buffered处理的IO, 意味着每一次读和写的请求都会由OS底层直接处理,这会导致非常低效的问题。

    经过Buffered处理过的输入流将会从一个buffer内存区域读取数据,本地API只会在buffer空了之后才会被调用(可能一次调用会填充很多数据进buffer)。

    经过Buffered处理过的输出流将会把数据写入到buffer中,本地API只会在buffer满了之后才会被调用

BufferedReader/BufferedWriter可以将字符流(Reader)包装成缓冲流,这是最常见用的做法。

另外,BufferedReader提供一个readLine()可以方便地读取一行,而FileInputStream和FileReader只能读取一个字节或者一个字符。

总结:

 1 public class HelloWorld {
 2 
 3     public static void main(String[] args) throws IOException  {
 4         
 5         
 6         try {
 7             /*将文件流包装成文件输入字节流*/
 8             FileInputStream  fi = new FileInputStream("C:\\Users\\Administrator\\workspace\\test1\\src\\1.txt");
 9             /*将输入字节流转成输入字符流*/
10             InputStreamReader Reader = new InputStreamReader(fi);
11             /*将输入字符流包装成输入缓冲字符流*/
12             BufferedReader br = new BufferedReader(Reader);
13         
14             System.out.println(br.readLine());
15             
16         } catch (FileNotFoundException e) {
17             // TODO Auto-generated catch block
18             e.printStackTrace();
19         }
20     }
21         
22 }

 当然,字节流也有对应的BufferedInputStream,不需要这么麻烦,这里只是为了体会包装的思想

posted @ 2019-03-19 20:50  hzhuan  阅读(183)  评论(0编辑  收藏  举报