首页 > 代码库 > Java IO流
Java IO流
1.流的概念
Java采用流的机制来实现输入/输出。
流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样,如下图:
输出流:
输入流:
2.Java输入输出流
InputStream:输入字节流。继承自InputStream的流都是用于向程序中输入数据的,且数据单位都是字节(8位 byte[])。
InputStream 是所有的输入字节流的父类,它是一个抽象类。
ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。PipedInputStream 是从与其它线程共用的管道中读取数据。
ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。
Inputstream类中的常用方法:
(1) public abstract int read( ):读取一个byte的数据,返回值是高位补0的int类型值。若返回值=-1说明没有读取到任何字节读取工作结束。
(2) public int read(byte b[ ]):读取b.length个字节的数据放到b数组中。返回值是读取的字节数。该方法实际上是调用下一个方法实现的
(3) public int read(byte b[ ], int off, int len):从输入流中最多读取len个字节的数据,存放到偏移量为off的b数组中。
(4) public int available( ):返回输入流中可以读取的字节数。注意:若输入阻塞,当前线程将被挂起,如果InputStream对象调用这个方法的话,它只会返回0,这个方法必须由继承InputStream类的子类对象调用才有用,
(5) public long skip(long n):忽略输入流中的n个字节,返回值是实际忽略的字节数, 跳过一些字节来读取
(6) public int close( ) :我们在使用完后,必须对我们打开的流进行关闭.
OutputSteam:输出字节流。继承自OutputStream的流都是程序用于向外输出数据的,且数据单位都是字节(8位 byte[])。
OutputStream 是所有的输出字节流的父类,它是一个抽象类。
ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据,
ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。
OutputSteam类中的常用方法:
(1) public void write(byte b[ ]):将参数b中的字节写到输出流。
(2) public void write(byte b[ ], int off, int len) :将参数b的从偏移量off开始的len个字节写到输出流。
(3) public abstract void write(int b) :先将int转换为byte类型,把低字节写入到输出流中。
(4) public void flush( ) : 将数据缓冲区中数据全部输出,并清空缓冲区。
(5) public void close( ) : 关闭输出流并释放与流相关的系统资源。
Reader:输入字符流。继承自Reader的流都是用于向程序中输入数据的,且数据单位都是字符(16位 char[])。
Reader 是所有的输入字符流的父类,它是一个抽象类。
CharReader、StringReader 是两种基本的介质流,它们分别将Char 数组、String中读取数据。PipedReader 是从与其它线程共用的管道中读取数据。
BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它Reader 对象。
FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号。
InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader 可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream 转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。
Reader类中的常用方法:
(1) public int read() throws IOException; //读取一个字符,返回值为读取的字符
(2) public int read(char cbuf[]) throws IOException; /*读取一系列字符到数组cbuf[]中,返回值为实际读取的字符的数量*/
(3) public abstract int read(char cbuf[],int off,int len) throws IOException; /*读取len个字符,从数组cbuf[]的下标off处开始存放,返回值为实际读取的字符数量,该方法必须由子类实现*/
Writer:输出字符流。继承自Writer的流都是程序用于向外输出数据的,且数据单位都是字符(16位 char[])。
Writer 是所有的输出字符流的父类,它是一个抽象类。
CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据。PipedWriter 是向与其它线程共用的管道中写入数据,
BufferedWriter 是一个装饰器为Writer 提供缓冲功能。
PrintWriter 和PrintStream 极其类似,功能和使用也非常相似。
OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类。
Writer类中的常用方法:
(1) public void write(int c) throws IOException; //将整型值c的低16位写入输出流
(2) public void write(char cbuf[]) throws IOException; //将字符数组cbuf[]写入输出流
(3) public abstract void write(char cbuf[],int off,int len) throws IOException; //将字符数组cbuf[]中的从索引为off的位置处开始的len个字符写入输出流
(4) public void write(String str) throws IOException; //将字符串str中的字符写入输出流
(5) public void write(String str,int off,int len) throws IOException; //将字符串str 中从索引off开始处的len个字符写入输出流
(6) flush( ) //刷空输出流,并输出所有被缓存的字节。
(7) close() 关闭流 public abstract void close() throws IOException
Java输入输出流有两个对称性
输入-输出对称: InputStream和OutputStream各自在Byte流输入和输出的两个平行结构的等级的根部;Reader和Writer各自在Char流输入和输出的两个平行结构的根部
byte-char对称:InputStream和Reader的子类分别负责Byte和Char流的输入;OutputStream和Writer的子类分别负责Byte和Char流的输出。分别形成平行的等级结构。
3.常用的IO流
1.字节流中原始流的代表:FileInputStream FileOutputStream
FileInputStream 从一个文件中读取byte[]
FileOutputStream 将byte[]写入到一个文件中
FileInputStream/FileOutputStream的例子
具体的内容是:从利用FileInputStream从input.txt中读出byte流,用某种编码格式转换为String显示出来,然后将String转换成byte流,利用FileOutputStream将byte流写入到output.txt中
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.FileNotFoundException; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.nio.ByteBuffer; 7 import java.nio.charset.Charset; 8 9 public class FileStreamDemo {10 public static void main(String[] args) {11 try {12 FileInputStream fis = new FileInputStream(new File("input.txt"));13 byte[] bis = new byte[fis.available()];14 fis.read(bis);15 fis.close();16 /*17 * 关于byte[]转换为String编码配置有两种方法,建议使用第二种方案 1.String str = new18 * String(b,"charsetname") 2.Charset charset = =19 * Charset.forName("charsetname"); String str =20 * charset.decode(ByteBuffer.wrap(b)).toString();21 */22 Charset charset = Charset.forName("UTF-8");23 String str = charset.decode(ByteBuffer.wrap(bis)).toString();24 // String str = new String(bis);25 // //byte转换为String,默认的编码是"ISO-8859-1",即根据编辑器的编码来确定编码方式26 System.out.println(str);27 28 FileOutputStream fos = new FileOutputStream(new File("output.txt"));29 byte[] bos = str.getBytes();30 fos.write(bos);31 fos.close();32 33 } catch (FileNotFoundException e) {34 // TODO Auto-generated catch block35 e.printStackTrace();36 } catch (IOException e) {37 // TODO Auto-generated catch block38 e.printStackTrace();39 }40 41 }42 }
2.字节流中装饰流之BufferInputStream BufferOutputStream
BufferInputStream:将原始InputStream中的byte[]读到内存缓存区中,然后从缓冲区读取byte[]
BufferOutputStream:向一个缓冲区中写入byte[],将缓冲区中的byte[]写入到原始outputStream中
BufferInputStream和BufferoutputStream对原始输入输出流进行装饰,使得流的读/写操作使用缓冲机制,这样不会对每次的流读/写操作都产生一个物理的读/写操作,从而提高了程序的效率。涉及物理流的地方,如控制台I/O,文件I/O等,都应当使用这个装饰流处理器。
举例:
1 import java.io.BufferedInputStream; 2 import java.io.BufferedOutputStream; 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 import java.nio.ByteBuffer; 9 import java.nio.charset.Charset;10 11 public class BufferStreamDemo {12 public static void main(String[] args) {13 try {14 15 FileInputStream fis = new FileInputStream(new File("input.txt"));16 BufferedInputStream bfis = new BufferedInputStream(fis);17 byte[] bis = new byte[bfis.available()];18 bfis.read(bis);19 bfis.close();20 fis.close();21 /*22 * 关于byte[]转换为String编码配置有两种方法,建议使用第二种方案 1.String str = new23 * String(b,"charsetname") 2.Charset charset = =24 * Charset.forName("charsetname"); String str =25 * charset.decode(ByteBuffer.wrap(b)).toString();26 */27 Charset charset = Charset.forName("UTF-8");28 String str = charset.decode(ByteBuffer.wrap(bis)).toString();29 // String str = new String(bis);30 // //byte转换为String,默认的编码是"ISO-8859-1",即根据编辑器的编码来确定编码方式31 System.out.println(str);32 33 FileOutputStream fos = new FileOutputStream(new File("output.txt"));34 BufferedOutputStream bfos = new BufferedOutputStream(fos);35 byte[] bos = str.getBytes();36 bfos.write(bos);37 bfos.close();38 fos.close();39 } catch (FileNotFoundException e) {40 // TODO Auto-generated catch block41 e.printStackTrace();42 } catch (IOException e) {43 // TODO Auto-generated catch block44 e.printStackTrace();45 }46 47 }48 }
3.字节装饰流之ObjectInputStream ObjectOutputStream
ObjectInputStream :对象输入流,将使用ObjectOutputStream串行化的原始数据类型和对象重新并行化
ObjectOutputStream:对象输出流,将原始数据类型和对象串行化
使用ObjectInputStream/ObjectOutputStream类所读写的对象必须实现Serializable接口,对象中的transient和static类型成员变量不会被读取和写入
举例:
1 import java.io.BufferedInputStream; 2 import java.io.BufferedOutputStream; 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 import java.nio.ByteBuffer; 9 import java.nio.charset.Charset;10 11 public class BufferStreamDemo {12 public static void main(String[] args) {13 try {14 15 FileInputStream fis = new FileInputStream(new File("input.txt"));16 BufferedInputStream bfis = new BufferedInputStream(fis);17 byte[] bis = new byte[bfis.available()];18 bfis.read(bis);19 bfis.close();20 fis.close();21 /*22 * 关于byte[]转换为String编码配置有两种方法,建议使用第二种方案 1.String str = new23 * String(b,"charsetname") 2.Charset charset = =24 * Charset.forName("charsetname"); String str =25 * charset.decode(ByteBuffer.wrap(b)).toString();26 */27 Charset charset = Charset.forName("UTF-8");28 String str = charset.decode(ByteBuffer.wrap(bis)).toString();29 // String str = new String(bis);30 // //byte转换为String,默认的编码是"ISO-8859-1",即根据编辑器的编码来确定编码方式31 System.out.println(str);32 33 FileOutputStream fos = new FileOutputStream(new File("output.txt"));34 BufferedOutputStream bfos = new BufferedOutputStream(fos);35 byte[] bos = str.getBytes();36 bfos.write(bos);37 bfos.close();38 fos.close();39 } catch (FileNotFoundException e) {40 // TODO Auto-generated catch block41 e.printStackTrace();42 } catch (IOException e) {43 // TODO Auto-generated catch block44 e.printStackTrace();45 }46 47 }48 }
1 import java.io.*; 2 3 public class Student implements Serializable { 4 5 String name; 6 int id; 7 int age; 8 String department; 9 10 public Student(String name, int id, int age, String department) {11 this.age = age;12 this.department = department;13 this.id = id;14 this.name = name;15 }16 }
4.字节装饰流之DataInputStream DataOutputStream
DataInputStream:提供基于多字节的读取方法,可以读取原始数据类型的数据
DataOutputStream:提供基于多字节的写出方法,可以写出原始数据类型的数据
举例:
1 public class Member { 2 private String name; 3 private int age; 4 5 public Member() { 6 } 7 8 public Member(String name, int age) { 9 this.name = name;10 this.age = age;11 }12 13 public void setName(String name) {14 this.name = name;15 }16 17 public void setAge(int age) {18 this.age = age;19 }20 21 public String getName() {22 return name;23 }24 25 public int getAge() {26 return age;27 }28 }
1 import java.io.*; 2 3 public class DataStreamDemo { 4 public static void main(String[] args) { 5 Member[] members = { new Member("Justin", 90), new Member("momor", 95), 6 new Member("Bush", 88) }; 7 try { 8 DataOutputStream dataOutputStream = new DataOutputStream( 9 new FileOutputStream(new File("file.txt")));10 11 for (Member member : members) {12 // 写入UTF字符串13 dataOutputStream.writeUTF(member.getName());14 // 写入int数据15 dataOutputStream.writeInt(member.getAge());16 }17 18 // 所有数据至目的地19 dataOutputStream.flush();20 // 关闭流21 dataOutputStream.close();22 23 DataInputStream dataInputStream = new DataInputStream(24 new FileInputStream(new File("file.txt")));25 26 // 读出数据并还原为对象27 for (int i = 0; i < members.length; i++) {28 // 读出UTF字符串29 String name = dataInputStream.readUTF();30 // 读出int数据31 int score = dataInputStream.readInt();32 members[i] = new Member(name, score);33 }34 35 // 关闭流36 dataInputStream.close();37 38 // 显示还原后的数据39 for (Member member : members) {40 System.out41 .printf("%s\t%d%n", member.getName(), member.getAge());42 }43 } catch (IOException e) {44 e.printStackTrace();45 }46 }47 }
5.字符流 之StringReader和StringWriter
StringReader:数据从String中读取到char[]
StringWriter:将char[]写入到String中
举例:
1 import java.io.IOException; 2 import java.io.StringReader; 3 import java.io.StringWriter; 4 5 public class StringStreamTest { 6 public static void main(String[] args) { 7 String str = "abcdefghijklmn"; 8 transform(str); 9 }10 11 public static void transform(String str) {12 StringReader sr = new StringReader(str);13 StringWriter sw = new StringWriter();14 char[] chars = new char[1024];15 try {16 int len = 0;17 while ((len = sr.read(chars)) != -1) {18 String strRead = new String(chars, 0, len).toUpperCase();19 System.out.println(strRead);20 sw.write(strRead);21 sw.flush();22 }23 sr.close();24 sw.close();25 } catch (IOException e) {26 e.printStackTrace();27 } finally {28 sr.close();29 try {30 sw.close();31 } catch (IOException e) {32 e.printStackTrace();33 }34 }35 }36 }
6.字符装饰流之 BufferedReader/BufferedWriter
BufferedReader/BufferedWriter的作用和BufferInputStream/BufferOutputStream类似,但BufferedReader提供了一个readline方法,可以将存储的一行的char[]读取出来
举例:
1 import java.io.*; 2 3 class BufferReaderDemo { 4 public static void main(String arg[]) throws IOException { 5 BufferedReader b = new BufferedReader(new FileReader("c.txt")); 6 boolean c; 7 do { 8 String s = b.readLine(); 9 System.out.println(s);10 } while (c = b.read() != -1);11 }12 }
7.从byte流到char流的适配 InputStreamReader和OutputStreamWriter
byte流到char流的适配是通过InputStreamReader和OutputStreamWriter来解决的
InputStreamReader:是字节流通向字符流的桥梁。你可以在构造器重指定编码的方式,如果不指定的话将采用底层操作系统的默认编码方式,例如 GBK 等
要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。
为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。例如:
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
OutputStreamWriter :是字符流通向字节流的桥梁。
每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积
为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。例如:
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
举例:
1 import java.io.BufferedReader; 2 import java.io.BufferedWriter; 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.io.InputStreamReader; 7 import java.io.OutputStreamWriter; 8 9 public class StreamReaderWriterDemo {10 public static void main(String[] args) {11 try {12 13 BufferedReader bufr = new BufferedReader(new InputStreamReader(14 new FileInputStream("f:\\01.txt")));15 16 BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(17 new FileOutputStream("f:\\02.txt")));18 19 int ch = 0;20 21 // 以字符方式显示文件内容22 while ((ch = bufr.read()) != -1) {23 System.out.print((char) ch);24 bufw.write(ch);25 }26 if (bufr != null)27 bufr.close();28 if (bufw != null)29 bufw.close();30 } catch (ArrayIndexOutOfBoundsException e) {31 e.printStackTrace();32 } catch (IOException e) {33 e.printStackTrace();34 }35 }36 }
8. InputStreamReader和OutputStreamWriter的子类:FileReader 和FileWriter
FileReader:文件字节流通向字符流的桥梁
FileWriter:是字符流通向文件字节流的桥梁。
举例:
1 import java.io.BufferedReader; 2 import java.io.BufferedWriter; 3 import java.io.FileReader; 4 import java.io.FileWriter; 5 import java.io.IOException; 6 7 public class TestWriter { 8 // 功能:读取E:/Test.txt文件的内容(一行一行读),并将其内容写入E:/Jack.txt中 9 // 知识点:java读文件、写文件---<以字符流方式>10 public static void main(String[] args) {11 try {12 // 创建FileReader对象,用来读取字符流13 FileReader fr = new FileReader("E:/Test.txt");14 // 缓冲指定文件的输入15 BufferedReader br = new BufferedReader(fr);16 // 创建FileWriter对象,用来写入字符流17 FileWriter fw = new FileWriter("E:/Jack.txt");18 // 将缓冲对文件的输出19 BufferedWriter bw = new BufferedWriter(fw);20 // 定义一个String类型的变量,用来每次读取一行21 String myreadline;22 while (br.ready()) {23 // 读取一行24 myreadline = br.readLine();25 // 写入文件26 bw.write(myreadline);27 bw.newLine();28 // 在屏幕上输出29 System.out.println(myreadline);30 }31 // 刷新该流的缓冲32 bw.flush();33 bw.close();34 br.close();35 fw.close();36 br.close();37 fr.close();38 39 } catch (IOException e) {40 e.printStackTrace();41 }42 }43 }
参考文章:
Java输入输出流详解 http://blog.csdn.net/zsw12013/article/details/6534619
Java IO流分析整理 http://www.th7.cn/Program/java/201406/214540.shtml
Java输入输出流 http://blog.csdn.net/hguisu/article/details/7418161
《Java与模式》第27章 专题:设计模式在Java I/O库中的应用
ObjectInputStream与ObjectOutputStream类 http://blog.sina.com.cn/s/blog_77cb34170100r5o6.html
使用StringReader和StringWriter操作字符串 http://blog.csdn.net/zhuhezan/article/details/6526915
InputStreamReader和OutputStreamWriter的用法 http://blog.csdn.net/z69183787/article/details/8179889
Java FileReader FileWriter 示例 http://blog.163.com/jackswu@yeah/blog/static/1406291232011076011170/
Java IO流