关于使用处理流的优势,归纳起来就是两点:(1)对于开发人员来说,使用处理流进行输入/输出操作更简单;(2)使用处理流执行效率更高。
1、BufferedInputStream/BufferedOutputStream和BufferedReader/BufferedWriter
Constructor | Description |
| Creates a |
| Creates a |
All MethodsInstance MethodsConcrete Methods
Modifier and Type | Method | Description |
|
| Returns an estimate of the number of bytes that can be read (or skipped over) from this input stream without blocking by the next invocation of a method for this input stream. |
|
| Closes this input stream and releases any system resources associated with the stream. |
|
| See the general contract of the |
|
| Tests if this input stream supports the |
|
| See the general contract of the |
|
| Reads bytes from this byte-input stream into the specified byte array, starting at the given offset. |
|
| See the general contract of the |
|
| See the general contract of the |
1 package com.zyjhandsome.io;
2
3 import java.io.*;
4
5 public class BufferedStreamTest1 {
6
7 public static void main(String[] args) {
8 // TODO Auto-generated method stub
9 try {
10 FileInputStream fis =
11 new FileInputStream("D:\\User_zhaoyingjun\\JavaSE\\Java_Eclipse_Workspace\\HelloWorld2\\src\\com\\zyjhandsome\\io\\BufferedStreamTest1.java");
12 BufferedInputStream bis = new BufferedInputStream(fis);
13 int c = 0;
14 System.out.println(bis.read());
15 System.out.println(bis.read());
16 bis.mark(10);
17 for (int i = 0; i < 10 && (c = bis.read()) != -1; i++)
18 {
19 System.out.print(c + " ");
20 }
21 System.out.println();
22 bis.reset();
23 for (int i = 0; i < 10 && (c = bis.read()) != -1; i++)
24 {
25 System.out.print(c + " ");
26 }
27 } catch (FileNotFoundException e2) {
28 // TODO Auto-generated catch block
29 e2.printStackTrace();
30 } catch (IOException e1) {
31 // TODO Auto-generated catch block
32 e1.printStackTrace();
33 }
34 }
35 }
输出结果:
1 112
2 97
3 99 107 97 103 101 32 99 111 109 46
4 99 107 97 103 101 32 99 111 109 46
Constructor | Description |
| Creates a buffered character-output stream that uses a default-sized output buffer. |
| Creates a new buffered character-output stream that uses an output buffer of the given size. |
Modifier and Type | Method | Description |
|
| Closes the stream, flushing it first. |
|
| Flushes the stream. |
|
| Writes a line separator. |
|
| Writes a portion of an array of characters. |
|
| Writes a single character. |
|
| Writes a portion of a String. |
Constructor | Description |
| Creates a buffering character-input stream that uses a default-sized input buffer. |
| Creates a buffering character-input stream that uses an input buffer of the specified size. |
All MethodsInstance MethodsConcrete Methods
Modifier and Type | Method | Description |
|
| Closes the stream and releases any system resources associated with it. |
|
| Returns a |
|
| Marks the present position in the stream. |
|
| Tells whether this stream supports the mark() operation, which it does. |
|
| Reads a single character. |
|
| Reads characters into a portion of an array. |
|
| Reads a line of text. |
|
| Tells whether this stream is ready to be read. |
|
| Resets the stream to the most recent mark. |
|
| Skips characters. |
1 package com.zyjhandsome.io;
2
3 import java.io.*;
4
5 public class BufferedStreamTest2 {
6
7 public static void main(String[] args) {
8 // TODO Auto-generated method stub
9 try {
10 BufferedWriter bw = new BufferedWriter(
11 new FileWriter("D:\\User_zhaoyingjun\\JavaSE\\Test\\BufferedStreamTest2.dat"));
12 BufferedReader br = new BufferedReader(
13 new FileReader("D:\\User_zhaoyingjun\\JavaSE\\Test\\BufferedStreamTest2.dat"));
14 String s = null;
15 for (int i = 0; i <= 100; i++)
16 {
17 s = String.valueOf(Math.random());
18 bw.write(s);
19 bw.newLine();
20 }
21 bw.flush();
22 while ((s = br.readLine()) != null)
23 {
24 System.out.println(s);
25 }
26 bw.close();
27 br.close();
28 } catch (IOException e) {
29 // TODO Auto-generated catch block
30 e.printStackTrace();
31 }
32 }
33 }
2、处理流的用法(PrintStream)
下面程序使用PrintStream处理流来包装OutputStream,使用处理流后的输出流在输出时将更加方便。
PrintWriter和PrintStream都属于输出流,分别针对字符和字节。
PrintWriter和PrintStream提供了重载print、println方法用于多种数据类型的输出。
PrintWriter和PrintStream的输出不会抛出异常,用户通过检测错误状态获取错误信息。
PrintWriter和PrintStream有自动flush功能。
Constructor | Description |
| Creates a new print stream, without automatic line flushing, with the specified file. |
| Creates a new print stream, without automatic line flushing, with the specified file and charset. |
| Creates a new print stream. |
| Creates a new print stream. |
| Creates a new print stream. |
| Creates a new print stream, without automatic line flushing, with the specified file name. |
| Creates a new print stream, without automatic line flushing, with the specified file name and charset. |
Constructor | Description |
| Creates a new PrintWriter, without automatic line flushing, with the specified file. |
| Creates a new PrintWriter, without automatic line flushing, with the specified file and charset. |
| Creates a new PrintWriter, without automatic line flushing, from an existing OutputStream. |
| Creates a new PrintWriter from an existing OutputStream. |
| Creates a new PrintWriter, without automatic line flushing. |
| Creates a new PrintWriter. |
| Creates a new PrintWriter, without automatic line flushing, with the specified file name. |
| Creates a new PrintWriter, without automatic line flushing, with the specified file name and charset. |
1 package com.zyjhandsome.io;
2
3 import java.io.*;
4
5 public class PrintStreamTest {
6
7 public static void main(String[] args) {
8 // TODO Auto-generated method stub
9 try {
10 FileOutputStream fos = new FileOutputStream("D:\\User_zhaoyingjun\\JavaSE\\Test\\PrintStreamTest.txt");
11 PrintStream ps = new PrintStream(fos);
12 // 使用PrintStream执行输出
13 ps.println("普通字符串");
14 // 直接使用PrintStream输出对象
15 ps.println(new PrintStreamTest());
16 ps.close();
17 } catch (FileNotFoundException e) {
18 // TODO Auto-generated catch block
19 e.printStackTrace();
20 }
21 }
22 }
输出结果(文件“PrintStreamTest.txt”中的内容):
1 普通字符串
2 com.zyjhandsome.io.PrintStreamTest@71be98f5
由于PrintStream类的输出功能非常强大,通常如果需要输出文本内容,都应该将输出流包装成PrintStream后进行输出。
在选择字节流或者字符流时,通常有一个规则:如果进行输入/输出的内容是文本内容,则应该考虑使用字符流;如果进行输入/输出的内容是二进制那内容,则应该考虑使用字节流。
1 package com.zyjhandsome.io;
2
3 import java.io.*;
4
5 public class TestPrintStream {
6
7 public static void main(String[] args) {
8 // TODO Auto-generated method stub
9 PrintStream ps = null;
10 try {
11 FileOutputStream fos = new FileOutputStream("D:\\User_zhaoyingjun\\JavaSE\\Test\\TestPrintStream1.log");
12 ps = new PrintStream(fos);
13 } catch (FileNotFoundException e) {
14 // TODO Auto-generated catch block
15 e.printStackTrace();
16 }
17 if (ps != null)
18 {
19 System.setOut(ps);
20 }
21 int ln = 0;
22 // char型,16-bit
23 for (char c = 0; c <= 60000; c++)
24 {
25 System.out.println(c + "");
26 if (ln++ >= 100)
27 {
28 System.out.println();
29 ln = 0;
30 }
31
32 }
33 ps.close();
34 }
35 }
1 package com.zyjhandsome.io;
2
3 import java.io.*;
4
5 public class TestPrintStream2 {
6
7 public static void main(String[] args) {
8 // TODO Auto-generated method stub
9 String fileName = args[0];
10 if (fileName != null)
11 {
12 list_test(fileName, System.out);
13 }
14 }
15 public static void list_test(String f, PrintStream ps)
16 {
17 try {
18 // 在字符流FileReader外面套了一个BufferReader,BufferReader类中有readLine()方法可以读取一行的内容
19 BufferedReader br = new BufferedReader(new FileReader(f));
20 String s = null;
21 while ((s = br.readLine()) != null)
22 {
23 ps.println(s);
24 }
25 br.close();
26 } catch (FileNotFoundException e) {
27 // TODO Auto-generated catch block
28 e.printStackTrace();
29 } catch (IOException e) {
30 // TODO Auto-generated catch block
31 e.printStackTrace();
32 ps.println("无法读取文件");
33 }
34 }
35 }
1 package com.zyjhandsome.io;
2
3 import java.util.*;
4 import java.io.*;
5
6 public class TestPrintStream3 {
7
8 public static void main(String[] args) {
9 // TODO Auto-generated method stub
10 String s = null;
11 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
12 try {
13 FileWriter fw = new FileWriter("D:\\User_zhaoyingjun\\JavaSE\\Test\\TestPrintStream3.log");
14 // 也可以选择使用追加(增加文本内容)形式
15 // FileWriter fw = new FileWriter("D:\\User_zhaoyingjun\\JavaSE\\Test\\TestPrintStream3.log", true);
16 PrintWriter log = new PrintWriter(fw);
17 while ( (s = br.readLine()) != null )
18 {
19 if (s.equals("exit"))
20 {
21 break;
22 // System.exit(-1);
23 }
24 System.out.println(s.toUpperCase());
25 log.println("--------");
26 log.println(s.toUpperCase());
27 }
28 log.println("===" + new Date() + "===");
29 log.flush();
30 log.close();
31 } catch (IOException e) {
32 // TODO Auto-generated catch block
33 e.printStackTrace();
34 }
35 }
36 }
输出结果:
1 hi
2 HI
3 hello
4 HELLO
5 hah
6 HAH
7 exit
在“TestPrintStream3.log”文件中输出结果:
--------
HI
--------
HELLO
--------
HAH
===Tue Sep 25 09:12:42 CST 2018===
3、输入/输出流体系
StringWriter和StringReader:
Constructor | Description |
| Creates a new string reader. |
All MethodsInstance MethodsConcrete Methods
Modifier and Type | Method | Description |
|
| Closes the stream and releases any system resources associated with it. |
|
| Marks the present position in the stream. |
|
| Tells whether this stream supports the mark() operation, which it does. |
|
| Reads a single character. |
|
| Reads characters into a portion of an array. |
|
| Tells whether this stream is ready to be read. |
|
| Resets the stream to the most recent mark, or to the beginning of the string if it has never been marked. |
|
| Skips the specified number of characters in the stream. |
Constructor | Description |
| Create a new string writer using the default initial string-buffer size. |
| Create a new string writer using the specified initial string-buffer size. |
All MethodsInstance MethodsConcrete Methods
Modifier and Type | Method | Description |
|
| Appends the specified character to this writer. |
|
| Appends the specified character sequence to this writer. |
|
| Appends a subsequence of the specified character sequence to this writer. |
|
| Closing a |
|
| Flush the stream. |
|
| Return the string buffer itself. |
|
| Return the buffer's current value as a string. |
|
| Write a portion of an array of characters. |
|
| Write a single character. |
|
| Write a string. |
|
| Write a portion of a string. |
1 package com.zyjhandsome.io;
2
3 import java.io.*;
4
5 public class StringNodeTest {
6
7 public static void main(String[] args) {
8 // TODO Auto-generated method stub
9 String src = "从明天起,做一个幸福的人\n"
10 + "喂马,劈柴,周游世界\n"
11 + "从明天起,关心粮食和蔬菜\n"
12 + "我有一所房子,面朝大海,春暖花开\n"
13 + "从明天起,和每一个亲人通信\n"
14 + "告诉他们我的幸福\n";
15 char[] buffer = new char[32];
16 int hasRead = 0;
17 try {
18 StringReader sr = new StringReader(src);
19 // 采用循环方式读取字符串
20 while((hasRead = sr.read(buffer)) != -1)
21 {
22 System.out.print(new String(buffer, 0, hasRead));
23 }
24 } catch (Exception e) {
25 // TODO Auto-generated catch block
26 e.printStackTrace();
27 }
28 try {
29 StringWriter sw = new StringWriter();
30 // 调用StringWriter的方法执行输出
31 // 调用StringWriter的方法执行输出
32 sw.write("有一个美丽的新世界,\n");
33 sw.write("她在远方等我,\n");
34 sw.write("哪里有天真的孩子,\n");
35 sw.write("还有姑娘的酒窝\n");
36 System.out.println("----下面是sw的字符串节点里的内容----");
37 // 使用toString()方法返回StringWtiter字符串节点的内容
38 System.out.println(sw.toString());
39 } catch (Exception e) {
40 // TODO Auto-generated catch block
41 e.printStackTrace();
42 }
43 }
44 }
输出结果:
1 从明天起,做一个幸福的人
2 喂马,劈柴,周游世界
3 从明天起,关心粮食和蔬菜
4 我有一所房子,面朝大海,春暖花开
5 从明天起,和每一个亲人通信
6 告诉他们我的幸福
7 ----下面是sw的字符串节点里的内容----
8 有一个美丽的新世界,
9 她在远方等我,
10 哪里有天真的孩子,
11 还有姑娘的酒窝
4、转换流
输入/输出流体系中还提供了两个转换流,这两个转换流用于实现将字节流转换成字符流,其中InputStringReader将输入字节流转换成字符输入流,OutputStringWriter将输出字节流转换成字符输出流。
Java使用System.in(这是一个InputStream字节流)代表标准输入,即键盘输入,使用不太方便,而且键盘那内容都是文本内容,所以可以使用InputStreamReader将其转换成字符输入流,普通的Reader读取输入内容时也不太方便,可以将普通的Reader再次包装成BufferedReader,利用BufferedReader的readLine()方法可以一次读取一行内容。如下程序所示。
1 package com.zyjhandsome.io;
2
3 import java.io.*;
4
5 public class TransFormKeyinTest {
6
7 public static void main(String[] args) {
8 // TODO Auto-generated method stub
9 InputStreamReader reader = new InputStreamReader(System.in);
10 BufferedReader br = new BufferedReader(reader);
11 String s = null;
12 try {
13 s = br.readLine();
14 while (s != null)
15 {
16 if (s.equals("exit"))
17 {
18 System.exit(1);
19 }
20 System.out.println(s.toUpperCase());
21 s = br.readLine();
22 }
23 br.close();
24 } catch (IOException e) {
25 // TODO Auto-generated catch block
26 e.printStackTrace();
27 }
28 }
29 }
输出结果:
1 hello
2 HELLO
3 how are you.
4 HOW ARE YOU.
1 package com.zyjhandsome.io;
2
3 import java.io.*;
4
5 public class TransFormTest1 {
6
7 public static void main(String[] args) {
8 // TODO Auto-generated method stub
9 try {
10 OutputStreamWriter ows = new OutputStreamWriter(
11 new FileOutputStream("D:\\User_zhaoyingjun\\JavaSE\\Test\\TransFormTest1.txt"));
12 ows.write("microsoft...");
13 // 获取当前输出流的编码方式
14 System.out.println(ows.getEncoding());
15 ows.close();
16 // FileOutputStream中第二个参数true代表是否在文件中追加内容
17 ows = new OutputStreamWriter(
18 new FileOutputStream("D:\\User_zhaoyingjun\\JavaSE\\Test\\TransFormTest1.txt", true),
19 "ISO8859_1");
20 ows.write("microsoft...");
21 // 获取当前输出流的编码方式
22 System.out.println(ows.getEncoding());
23 ows.close();
24 } catch (FileNotFoundException e2) {
25 // TODO Auto-generated catch block
26 e2.printStackTrace();
27 } catch (IOException e1) {
28 // TODO Auto-generated catch block
29 e1.printStackTrace();
30 }
31 }
32 }
输出结果:
1 GBK
2 ISO8859_1
5、推回输入流
在输入/输出流体系中,有两个特殊的流与众不同,就是PushbackInputStream和PushbackReader,它们提供的方法如下所示。
PushbackInputStream的构造器及方法:
Constructor | Description |
| Creates a |
| Creates a |
All MethodsInstance MethodsConcrete Methods
Modifier and Type | Method | Description |
|
| Returns an estimate of the number of bytes that can be read (or skipped over) from this input stream without blocking by the next invocation of a method for this input stream. |
|
| Closes this input stream and releases any system resources associated with the stream. |
|
| Marks the current position in this input stream. |
|
| Tests if this input stream supports the |
|
| Reads the next byte of data from this input stream. |
|
| Reads up to |
|
| Repositions this stream to the position at the time the |
|
| Skips over and discards |
|
| Pushes back an array of bytes by copying it to the front of the pushback buffer.(将一个字节数组内容推回到推回缓冲区里,从而允许重复读取刚刚读取的内容) |
|
| Pushes back a portion of an array of bytes by copying it to the front of the pushback buffer.(将一个字节数组里从off开始,长度为len字节的内容推回到推回缓冲区里,从而允许重复读取刚刚读取的内容) |
|
| Pushes back a byte by copying it to the front of the pushback buffer.(将一个字节推回到推回缓冲区里,从而允许重复读取刚刚读取的内容) |
PushbackReader的构造器和方法:
Constructor | Description |
| Creates a new pushback reader with a one-character pushback buffer. |
| Creates a new pushback reader with a pushback buffer of the given size. |
All MethodsInstance MethodsConcrete Methods
Modifier and Type | Method | Description |
|
| Closes the stream and releases any system resources associated with it. |
|
| Marks the present position in the stream. |
|
| Tells whether this stream supports the mark() operation, which it does not. |
|
| Reads a single character. |
|
| Reads characters into a portion of an array. |
|
| Tells whether this stream is ready to be read. |
|
| Resets the stream. |
|
| Skips characters. |
|
| Pushes back an array of characters by copying it to the front of the pushback buffer.(将一个字符数组内容推回到推回缓冲区里,从而允许重复读取刚刚读取的内容) |
|
| Pushes back a portion of an array of characters by copying it to the front of the pushback buffer. (将一个字符数组里从off开始,长度为len字节的内容推回到推回缓冲区里,从而允许重复读取刚刚读取的内容) |
|
| Pushes back a single character by copying it to the front of the pushback buffer.(将一个字符推回到推回缓冲区里,从而允许重复读取刚刚读取的内容) |
可以发现最后三个方法与InputStream和Reader中的三个read()方法一一对应,这三个方法就是PushbackInputStream和PushbackReader的奥秘所在。
这两个推回输入流都带有一个推回缓冲区,当程序调用这两个推回输入流的unread()方法时,系统将会把指定数组的内容推回到该缓冲区里,而推回输入流每次调用read()方法时总是先从推回缓冲区读取,只有完全读取了推回缓冲区的内容后,但还没有装满read()所需要的数组时才会从原输入流中读取。
当创建一个PushbackInputStream和PushbackReader时需要指定推回缓冲区的大小,默认的推回缓冲区的长度为1。如果程序中推回到推回缓冲区的内容超出了推回 缓冲区的大小,将会引发Pushback buffer overflow的IOException异常。
1 package com.zyjhandsome.io;
2
3 import java.io.*;
4
5 public class PushbackTest {
6
7 public static void main(String[] args) {
8 // TODO Auto-generated method stub
9 try {
10 // 创建一个PushbackReader对象,指定退回缓冲区的长度为64
11 PushbackReader pr = new PushbackReader(
12 new FileReader("D:\\User_zhaoyingjun\\JavaSE\\Java_Eclipse_Workspace\\HelloWorld2\\src\\com\\zyjhandsome\\io\\PushbackTest.java"), 64);
13 char[] buf = new char[32];
14 // 用于保存上次读取的字符串内容
15 String lastContent = "";
16 int hasRead = 0;
17 // 循环读取文件内容
18 while ((hasRead = pr.read(buf)) > 0)
19 {
20 // 将读取的内容转换成字符串
21 String content = new String(buf, 0, hasRead);
22 int targetIndex = 0;
23 // 将上次读取大的字符串和本次读取的字符串拼起来
24 // 查看是否包含目标字符串,如果包含目标字符串
25 if ( (targetIndex = (lastContent + content).indexOf("new PushbackReader")) > 0)
26 {
27 // 将本次内容和上次内容一起推回到缓冲区
28 pr.unread((lastContent + content).toCharArray());
29 // 重新定义一个长度为targetIndex的char数组
30 if (targetIndex > 32)
31 {
32 buf = new char[targetIndex];
33 }
34 // 再次读取指定长度的内容(就是目标字符串之间的内容 )
35 pr.read(buf, 0, targetIndex);
36 // 打印去读的内容
37 System.out.print(new String(buf , 0 ,targetIndex));
38 System.exit(0);
39 }
40 else
41 {
42 // 打印上次读取的内容
43 System.out.print(lastContent);
44 lastContent = content;
45 }
46 }
47 } catch (FileNotFoundException e2) {
48 // TODO Auto-generated catch block
49 e2.printStackTrace();
50 } catch (IOException e1) {
51 // TODO Auto-generated catch block
52 e1.printStackTrace();
53 }
54 }
55 }
输出结果:
1 package com.zyjhandsome.io;
2
3 import java.io.*;
4
5 public class PushbackTest {
6
7 public static void main(String[] args) {
8 // TODO Auto-generated method stub
9 try {
10 // 创建一个PushbackReader对象,指定退回缓冲区的长度为64
11 PushbackReader pr = new PushbackReader(
12 new FileReader("D:\\User_zhaoyingjun\\JavaSE\\Java_Eclipse_Workspace\\HelloWorld2\\src\\com\\zyjhandsome\\io\\PushbackTest.java"), 64);
13 char[] buf = new char[32];
14 // 用于保存上次读取的字符串内容
15 String lastContent = "";
16 int hasRead = 0;
17 // 循环读取文件内容
18 while ((hasRead = pr.read(buf)) > 0)
19 {
20 // 将读取的内容转换成字符串
21 String content = new String(buf, 0, hasRead);
22 int targetIndex = 0;
23 // 将上次读取大的字符串和本次读取的字符串拼起来
24 // 查看是否包含目标字符串,如果包含目标字符串
25 if ( (targetIndex = (lastContent + content).indexOf("