Java 输入/输出——处理流(BufferedStream、PrintStream、转换流、推回输入流)

时间:2023-03-09 06:07:09
Java 输入/输出——处理流(BufferedStream、PrintStream、转换流、推回输入流)

  关于使用处理流的优势,归纳起来就是两点:(1)对于开发人员来说,使用处理流进行输入/输出操作更简单;(2)使用处理流执行效率更高。

1、BufferedInputStream/BufferedOutputStream和BufferedReader/BufferedWriter

Constructor Description
BufferedInputStream​(InputStream in)
Creates a BufferedInputStream and saves its argument, the input stream in, for later use.
BufferedInputStream​(InputStream in, int size)
Creates a BufferedInputStream with the specified buffer size, and saves its argument, the input streamin, for later use.       

  

All MethodsInstance MethodsConcrete Methods
Modifier and Type Method Description
int available​()
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.
void close​()
Closes this input stream and releases any system resources associated with the stream.
void mark​(int readlimit)
See the general contract of the mark method of InputStream.
boolean markSupported​()
Tests if this input stream supports the mark and reset methods.
int read​()
See the general contract of the read method of InputStream.
int read​(byte[] b, int off, int len)
Reads bytes from this byte-input stream into the specified byte array, starting at the given offset.
void reset​()
See the general contract of the reset method of InputStream.
long skip​(long n)
See the general contract of the skip method of InputStream.
 package com.zyjhandsome.io;

 import java.io.*;

 public class BufferedStreamTest1 {

     public static void main(String[] args) {
// TODO Auto-generated method stub
try {
FileInputStream fis =
new FileInputStream("D:\\User_zhaoyingjun\\JavaSE\\Java_Eclipse_Workspace\\HelloWorld2\\src\\com\\zyjhandsome\\io\\BufferedStreamTest1.java");
BufferedInputStream bis = new BufferedInputStream(fis);
int c = 0;
System.out.println(bis.read());
System.out.println(bis.read());
bis.mark(10);
for (int i = 0; i < 10 && (c = bis.read()) != -1; i++)
{
System.out.print(c + " ");
}
System.out.println();
bis.reset();
for (int i = 0; i < 10 && (c = bis.read()) != -1; i++)
{
System.out.print(c + " ");
}
} catch (FileNotFoundException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}

  输出结果:

 112
97
99 107 97 103 101 32 99 111 109 46
99 107 97 103 101 32 99 111 109 46
Constructor Description
BufferedWriter​(Writer out)
Creates a buffered character-output stream that uses a default-sized output buffer.
BufferedWriter​(Writer out, int sz)
Creates a new buffered character-output stream that uses an output buffer of the given size.                                                                
Modifier and Type Method Description
void close​()
Closes the stream, flushing it first.
void flush​()
Flushes the stream.
void newLine​()
Writes a line separator.
void write​(char[] cbuf, int off, int len)
Writes a portion of an array of characters.                                                                                           
void write​(int c)
Writes a single character.
void write​(String s, int off, int len)
Writes a portion of a String.
Constructor Description
BufferedReader​(Reader in)
Creates a buffering character-input stream that uses a default-sized input buffer.
BufferedReader​(Reader in, int sz)
Creates a buffering character-input stream that uses an input buffer of the specified size.                                                                       
All MethodsInstance MethodsConcrete Methods
Modifier and Type Method Description
void close​()
Closes the stream and releases any system resources associated with it.
Stream<String> lines​()
Returns a Stream, the elements of which are lines read from this BufferedReader.                        
void mark​(int readAheadLimit)
Marks the present position in the stream.
boolean markSupported​()
Tells whether this stream supports the mark() operation, which it does.                                                   
int read​()
Reads a single character.
int read​(char[] cbuf, int off, int len)
Reads characters into a portion of an array.
String readLine​()
Reads a line of text.
boolean ready​()
Tells whether this stream is ready to be read.
void reset​()
Resets the stream to the most recent mark.
long skip​(long n)
Skips characters.
 package com.zyjhandsome.io;

 import java.io.*;

 public class BufferedStreamTest2 {

     public static void main(String[] args) {
// TODO Auto-generated method stub
try {
BufferedWriter bw = new BufferedWriter(
new FileWriter("D:\\User_zhaoyingjun\\JavaSE\\Test\\BufferedStreamTest2.dat"));
BufferedReader br = new BufferedReader(
new FileReader("D:\\User_zhaoyingjun\\JavaSE\\Test\\BufferedStreamTest2.dat"));
String s = null;
for (int i = 0; i <= 100; i++)
{
s = String.valueOf(Math.random());
bw.write(s);
bw.newLine();
}
bw.flush();
while ((s = br.readLine()) != null)
{
System.out.println(s);
}
bw.close();
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

2、处理流的用法(PrintStream)

  下面程序使用PrintStream处理流来包装OutputStream,使用处理流后的输出流在输出时将更加方便。

  PrintWriter和PrintStream都属于输出流,分别针对字符和字节。

  PrintWriter和PrintStream提供了重载print、println方法用于多种数据类型的输出。

  PrintWriter和PrintStream的输出不会抛出异常,用户通过检测错误状态获取错误信息。

  PrintWriter和PrintStream有自动flush功能。

Constructor Description
PrintStream​(File file)
Creates a new print stream, without automatic line flushing, with the specified file.
PrintStream​(File file, String csn)
Creates a new print stream, without automatic line flushing, with the specified file and charset.
PrintStream​(OutputStream out)
Creates a new print stream.
PrintStream​(OutputStream out, boolean autoFlush)
Creates a new print stream.
PrintStream​(OutputStream out, boolean autoFlush,String encoding)
Creates a new print stream.
PrintStream​(String fileName)
Creates a new print stream, without automatic line flushing, with the specified file name.
PrintStream​(String fileName, String csn)
Creates a new print stream, without automatic line flushing, with the specified file name and charset.
Constructor Description
PrintWriter​(File file)
Creates a new PrintWriter, without automatic line flushing, with the specified file.
PrintWriter​(File file, String csn)
Creates a new PrintWriter, without automatic line flushing, with the specified file and charset.
PrintWriter​(OutputStream out)
Creates a new PrintWriter, without automatic line flushing, from an existing OutputStream.
PrintWriter​(OutputStream out, boolean autoFlush)
Creates a new PrintWriter from an existing OutputStream.
PrintWriter​(Writer out)
Creates a new PrintWriter, without automatic line flushing.
PrintWriter​(Writer out, boolean autoFlush)
Creates a new PrintWriter.
PrintWriter​(String fileName)
Creates a new PrintWriter, without automatic line flushing, with the specified file name.
PrintWriter​(String fileName, String csn)
Creates a new PrintWriter, without automatic line flushing, with the specified file name and charset.                                
 package com.zyjhandsome.io;

 import java.io.*;

 public class PrintStreamTest {

     public static void main(String[] args) {
// TODO Auto-generated method stub
try {
FileOutputStream fos = new FileOutputStream("D:\\User_zhaoyingjun\\JavaSE\\Test\\PrintStreamTest.txt");
PrintStream ps = new PrintStream(fos);
// 使用PrintStream执行输出
ps.println("普通字符串");
// 直接使用PrintStream输出对象
ps.println(new PrintStreamTest());
ps.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

  输出结果(文件“PrintStreamTest.txt”中的内容):

 普通字符串
com.zyjhandsome.io.PrintStreamTest@71be98f5

  由于PrintStream类的输出功能非常强大,通常如果需要输出文本内容,都应该将输出流包装成PrintStream后进行输出。

  在选择字节流或者字符流时,通常有一个规则:如果进行输入/输出的内容是文本内容,则应该考虑使用字符流;如果进行输入/输出的内容是二进制那内容,则应该考虑使用字节流。

 package com.zyjhandsome.io;

 import java.io.*;

 public class TestPrintStream {

     public static void main(String[] args) {
// TODO Auto-generated method stub
PrintStream ps = null;
try {
FileOutputStream fos = new FileOutputStream("D:\\User_zhaoyingjun\\JavaSE\\Test\\TestPrintStream1.log");
ps = new PrintStream(fos);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (ps != null)
{
System.setOut(ps);
}
int ln = 0;
// char型,16-bit
for (char c = 0; c <= 60000; c++)
{
System.out.println(c + "");
if (ln++ >= 100)
{
System.out.println();
ln = 0;
} }
ps.close();
}
}
 package com.zyjhandsome.io;

 import java.io.*;

 public class TestPrintStream2 {

     public static void main(String[] args) {
// TODO Auto-generated method stub
String fileName = args[0];
if (fileName != null)
{
list_test(fileName, System.out);
}
}
public static void list_test(String f, PrintStream ps)
{
try {
// 在字符流FileReader外面套了一个BufferReader,BufferReader类中有readLine()方法可以读取一行的内容
BufferedReader br = new BufferedReader(new FileReader(f));
String s = null;
while ((s = br.readLine()) != null)
{
ps.println(s);
}
br.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
ps.println("无法读取文件");
}
}
}

  

 package com.zyjhandsome.io;

 import java.util.*;
import java.io.*; public class TestPrintStream3 { public static void main(String[] args) {
// TODO Auto-generated method stub
String s = null;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
FileWriter fw = new FileWriter("D:\\User_zhaoyingjun\\JavaSE\\Test\\TestPrintStream3.log");
// 也可以选择使用追加(增加文本内容)形式
// FileWriter fw = new FileWriter("D:\\User_zhaoyingjun\\JavaSE\\Test\\TestPrintStream3.log", true);
PrintWriter log = new PrintWriter(fw);
while ( (s = br.readLine()) != null )
{
if (s.equals("exit"))
{
break;
// System.exit(-1);
}
System.out.println(s.toUpperCase());
log.println("--------");
log.println(s.toUpperCase());
}
log.println("===" + new Date() + "===");
log.flush();
log.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

  输出结果:

 hi
HI
hello
HELLO
hah
HAH
exit

  在“TestPrintStream3.log”文件中输出结果:

--------
HI
--------
HELLO
--------
HAH
===Tue Sep 25 09:12:42 CST 2018===

3、输入/输出流体系

  StringWriter和StringReader:

Constructor Description
StringReader​(String s)
Creates a new string reader.                                                                                                                                                                                     
All MethodsInstance MethodsConcrete Methods
Modifier and Type Method Description
void close​()
Closes the stream and releases any system resources associated with it.
void mark​(int readAheadLimit)
Marks the present position in the stream.
boolean markSupported​()
Tells whether this stream supports the mark() operation, which it does.
int read​()
Reads a single character.
int read​(char[] cbuf, int off, int len)
Reads characters into a portion of an array.
boolean ready​()
Tells whether this stream is ready to be read.
void reset​()
Resets the stream to the most recent mark, or to the beginning of the string if it has never been marked.  
long skip​(long ns)
Skips the specified number of characters in the stream.
Constructor Description
StringWriter​()
Create a new string writer using the default initial string-buffer size.                                                                                                              
StringWriter​(int initialSize)
Create a new string writer using the specified initial string-buffer size.
All MethodsInstance MethodsConcrete Methods
Modifier and Type Method Description
StringWriter append​(char c)
Appends the specified character to this writer.
StringWriter append​(CharSequence csq)
Appends the specified character sequence to this writer.
StringWriter append​(CharSequence csq, int start, int end)
Appends a subsequence of the specified character sequence to this writer.                              
void close​()
Closing a StringWriter has no effect.
void flush​()
Flush the stream.
StringBuffer getBuffer​()
Return the string buffer itself.
String toString​()
Return the buffer's current value as a string.
void write​(char[] cbuf, int off, int len)
Write a portion of an array of characters.
void write​(int c)
Write a single character.
void write​(String str)
Write a string.
void write​(String str, int off, int len)
Write a portion of a string.
 package com.zyjhandsome.io;

 import java.io.*;

 public class StringNodeTest {

     public static void main(String[] args) {
// TODO Auto-generated method stub
String src = "从明天起,做一个幸福的人\n"
+ "喂马,劈柴,周游世界\n"
+ "从明天起,关心粮食和蔬菜\n"
+ "我有一所房子,面朝大海,春暖花开\n"
+ "从明天起,和每一个亲人通信\n"
+ "告诉他们我的幸福\n";
char[] buffer = new char[32];
int hasRead = 0;
try {
StringReader sr = new StringReader(src);
// 采用循环方式读取字符串
while((hasRead = sr.read(buffer)) != -1)
{
System.out.print(new String(buffer, 0, hasRead));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
StringWriter sw = new StringWriter();
// 调用StringWriter的方法执行输出
// 调用StringWriter的方法执行输出
sw.write("有一个美丽的新世界,\n");
sw.write("她在远方等我,\n");
sw.write("哪里有天真的孩子,\n");
sw.write("还有姑娘的酒窝\n");
System.out.println("----下面是sw的字符串节点里的内容----");
// 使用toString()方法返回StringWtiter字符串节点的内容
System.out.println(sw.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

  输出结果:

 从明天起,做一个幸福的人
喂马,劈柴,周游世界
从明天起,关心粮食和蔬菜
我有一所房子,面朝大海,春暖花开
从明天起,和每一个亲人通信
告诉他们我的幸福
----下面是sw的字符串节点里的内容----
有一个美丽的新世界,
她在远方等我,
哪里有天真的孩子,
还有姑娘的酒窝

4、转换流

  输入/输出流体系中还提供了两个转换流,这两个转换流用于实现将字节流转换成字符流,其中InputStringReader将输入字节流转换成字符输入流,OutputStringWriter将输出字节流转换成字符输出流。

  Java使用System.in(这是一个InputStream字节流)代表标准输入,即键盘输入,使用不太方便,而且键盘那内容都是文本内容,所以可以使用InputStreamReader将其转换成字符输入流,普通的Reader读取输入内容时也不太方便,可以将普通的Reader再次包装成BufferedReader,利用BufferedReader的readLine()方法可以一次读取一行内容。如下程序所示。

 package com.zyjhandsome.io;

 import java.io.*;

 public class TransFormKeyinTest {

     public static void main(String[] args) {
// TODO Auto-generated method stub
InputStreamReader reader = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(reader);
String s = null;
try {
s = br.readLine();
while (s != null)
{
if (s.equals("exit"))
{
System.exit(1);
}
System.out.println(s.toUpperCase());
s = br.readLine();
}
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

  输出结果:

 hello
HELLO
how are you.
HOW ARE YOU.
 package com.zyjhandsome.io;

 import java.io.*;

 public class TransFormTest1 {

     public static void main(String[] args) {
// TODO Auto-generated method stub
try {
OutputStreamWriter ows = new OutputStreamWriter(
new FileOutputStream("D:\\User_zhaoyingjun\\JavaSE\\Test\\TransFormTest1.txt"));
ows.write("microsoft...");
// 获取当前输出流的编码方式
System.out.println(ows.getEncoding());
ows.close();
// FileOutputStream中第二个参数true代表是否在文件中追加内容
ows = new OutputStreamWriter(
new FileOutputStream("D:\\User_zhaoyingjun\\JavaSE\\Test\\TransFormTest1.txt", true),
"ISO8859_1");
ows.write("microsoft...");
// 获取当前输出流的编码方式
System.out.println(ows.getEncoding());
ows.close();
} catch (FileNotFoundException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}

  输出结果:

 GBK
ISO8859_1

5、推回输入流

  在输入/输出流体系中,有两个特殊的流与众不同,就是PushbackInputStream和PushbackReader,它们提供的方法如下所示。

  PushbackInputStream的构造器及方法:

Constructor Description
PushbackInputStream​(InputStream in)
Creates a PushbackInputStream with a 1-byte pushback buffer, and saves its argument, the input stream in, for later use.
PushbackInputStream​(InputStream in, int size)
Creates a PushbackInputStream with a pushback buffer of the specified size, and saves its argument, the input stream in, for later use.
All MethodsInstance MethodsConcrete Methods
Modifier and Type Method Description
int available​()
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.
void close​()
Closes this input stream and releases any system resources associated with the stream.
void mark​(int readlimit)
Marks the current position in this input stream.
boolean markSupported​()
Tests if this input stream supports the mark and reset methods, which it does not.
int read​()
Reads the next byte of data from this input stream.
int read​(byte[] b, int off, int len)
Reads up to len bytes of data from this input stream into an array of bytes.
void reset​()
Repositions this stream to the position at the time the mark method was last called on this input stream.
long skip​(long n)
Skips over and discards n bytes of data from this input stream.
void unread​(byte[] b)
Pushes back an array of bytes by copying it to the front of the pushback buffer.(将一个字节数组内容推回到推回缓冲区里,从而允许重复读取刚刚读取的内容)
void unread​(byte[] b, int off, int len)
Pushes back a portion of an array of bytes by copying it to the front of the pushback buffer.(将一个字节数组里从off开始,长度为len字节的内容推回到推回缓冲区里,从而允许重复读取刚刚读取的内容)
void unread​(int b)
Pushes back a byte by copying it to the front of the pushback buffer.(将一个字节推回到推回缓冲区里,从而允许重复读取刚刚读取的内容)

  PushbackReader的构造器和方法:

Constructor Description
PushbackReader​(Reader in)
Creates a new pushback reader with a one-character pushback buffer.
PushbackReader​(Reader in, int size)
Creates a new pushback reader with a pushback buffer of the given size.                                                                                           
All MethodsInstance MethodsConcrete Methods
Modifier and Type Method Description
void close​()
Closes the stream and releases any system resources associated with it.
void mark​(int readAheadLimit)
Marks the present position in the stream.
boolean markSupported​()
Tells whether this stream supports the mark() operation, which it does not.
int read​()
Reads a single character.
int read​(char[] cbuf, int off, int len)
Reads characters into a portion of an array.
boolean ready​()
Tells whether this stream is ready to be read.
void reset​()
Resets the stream.
long skip​(long n)
Skips characters.
void unread​(char[] cbuf)
Pushes back an array of characters by copying it to the front of the pushback buffer.(将一个字符数组内容推回到推回缓冲区里,从而允许重复读取刚刚读取的内容)
void unread​(char[] cbuf, int off, int len)
Pushes back a portion of an array of characters by copying it to the front of the pushback buffer. (将一个字符数组里从off开始,长度为len字节的内容推回到推回缓冲区里,从而允许重复读取刚刚读取的内容)
void unread​(int c)
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异常。

 package com.zyjhandsome.io;

 import java.io.*;

 public class PushbackTest {

     public static void main(String[] args) {
// TODO Auto-generated method stub
try {
// 创建一个PushbackReader对象,指定退回缓冲区的长度为64
PushbackReader pr = new PushbackReader(
new FileReader("D:\\User_zhaoyingjun\\JavaSE\\Java_Eclipse_Workspace\\HelloWorld2\\src\\com\\zyjhandsome\\io\\PushbackTest.java"), 64);
char[] buf = new char[32];
// 用于保存上次读取的字符串内容
String lastContent = "";
int hasRead = 0;
// 循环读取文件内容
while ((hasRead = pr.read(buf)) > 0)
{
// 将读取的内容转换成字符串
String content = new String(buf, 0, hasRead);
int targetIndex = 0;
// 将上次读取大的字符串和本次读取的字符串拼起来
// 查看是否包含目标字符串,如果包含目标字符串
if ( (targetIndex = (lastContent + content).indexOf("new PushbackReader")) > 0)
{
// 将本次内容和上次内容一起推回到缓冲区
pr.unread((lastContent + content).toCharArray());
// 重新定义一个长度为targetIndex的char数组
if (targetIndex > 32)
{
buf = new char[targetIndex];
}
// 再次读取指定长度的内容(就是目标字符串之间的内容 )
pr.read(buf, 0, targetIndex);
// 打印去读的内容
System.out.print(new String(buf , 0 ,targetIndex));
System.exit(0);
}
else
{
// 打印上次读取的内容
System.out.print(lastContent);
lastContent = content;
}
}
} catch (FileNotFoundException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}

  输出结果:

 package com.zyjhandsome.io;

 import java.io.*;

 public class PushbackTest {

     public static void main(String[] args) {
// TODO Auto-generated method stub
try {
// 创建一个PushbackReader对象,指定退回缓冲区的长度为64
PushbackReader pr = new PushbackReader(
new FileReader("D:\\User_zhaoyingjun\\JavaSE\\Java_Eclipse_Workspace\\HelloWorld2\\src\\com\\zyjhandsome\\io\\PushbackTest.java"), 64);
char[] buf = new char[32];
// 用于保存上次读取的字符串内容
String lastContent = "";
int hasRead = 0;
// 循环读取文件内容
while ((hasRead = pr.read(buf)) > 0)
{
// 将读取的内容转换成字符串
String content = new String(buf, 0, hasRead);
int targetIndex = 0;
// 将上次读取大的字符串和本次读取的字符串拼起来
// 查看是否包含目标字符串,如果包含目标字符串
if ( (targetIndex = (lastContent + content).indexOf("