Java中的IO分为两个部分,以InputStream和Reader为基类的输入类,以OutputStream和Writer为基类的输出类。其中InputStream和OutputStream以字节为单位进行IO,而Reader和Writer以字符为单位。java
除了输入输出,还有一系列类库称为Filter,或成为装饰器。对于输入可用FilterInputStream和FilterReader的派生类,输出可用FilterOutputStream和FilterWriter的派生类,其中FilterInputStream和FilterOutputStream以字节为单位,FilterReader和FilterWriter以字符为单位。缓存
还有一个独立与InputStream和OutputStream的—RandomAccessFile,用于对文件的读写,有点相似与C语言中的fopen()markdown
因此能够总结,全部以Stream结尾的都是以字节为单位,也成为流;以Reader或Writer结尾的都以字符为单位。Reader和Writer在java1.1中才出现,若是须要进行转换,能够使用InputStreamReader和OutputStreamWriter。dom
Filter是对输入或输出进行必定的控制,如缓存、读取或写入基本数据类型等,用于更改流的一些行为。spa
FilterInputStream的派生类:指针
FilterOutputStream的派生类:日志
Reader和Writer中所用的Filter与InputStream和OutputStream中的Filter对比:code
对于Filter的具体使用将在具体综合例子中讲到。对象
输入分为输入字节和输入字符,分别使用基类是InputStream和Reader,若是须要把InputStrema转化为Reader,能够使用InputStreamReader。如下是一些InputStream经常使用的派生类与Writer与之对应的派生类。继承
InputStream派生类:
Reader与之对应的派生类:
将InputStream转成Reader示例:
// 建立一个InputStream类型的对象 InputStream in = new FileInputStream("data.txt"); // InputStreamReader继承自Reader,其构造方法接受一个InputStream对象 Reader reader = new InputStreamReader(in);
输出分为输出字节和输出字符,分别使用基类是OutputStream和Writer,若是须要把OutputStrema转化为Writer,能够使用OutputStreamWriter。如下是一些OutputStream经常使用的派生类与Writer与之对应的派生类。
OutputStream派生类:
Writer与之对应的派生类:
将OutputStream转成Writer示例:
// 建立一个OutputStream类型的对象 OutputStream out=new FileOutputStream("data.txt"); // OutputStreamWriter继承自Writer,其构造方法接受一个OutputStream对象 Writer writer=new OutputStreamWriter(out);
一、打开一个文件,并把其中的内容逐行输出的屏幕上。为了提升效率,这里将使用第一种过滤器BufferedReader,可以对输入进行缓冲。
public class Read { public static void main(String[]args) throws Exception{ String file="data.txt"; read(file); } public static void read(String file) throws Exception{ BufferedReader in=new BufferedReader(new FileReader(file)); String s; while((s=in.readLine())!=null) System.out.println(s); in.close(); } }
二、从文件中按字节读取内容,须要用到DataInputStream过滤器,因为这里要对字节进行操做,因此要使用InputStream而不是Reader。其中对是不是用BufferedStream进行效率比较。
import java.io.*; public class ReadByte { public static void main(String[] args) throws Exception { String file = "data.txt"; long start; start = System.currentTimeMillis();// 记录运行开始时间 readWithBufferedInputStream(file); System.out.println("readWithBufferedInputStream use time:" + (System.currentTimeMillis() - start));// 运行结束时间-开始时间就是运行时间 start = System.currentTimeMillis(); readWithoutBufferedInputStream(file); System.out.println("readWithoutBufferedInputStream use time:" + (System.currentTimeMillis() - start)); } public static void readWithBufferedInputStream(String file) throws Exception { // 用BufferedInputStream进行读取文件 DataInputStream in = new DataInputStream(new BufferedInputStream( new FileInputStream(file))); while (in.available() != 0) // DataInputStream剩余的字符数不为零则表示还没输出结束 in.readByte(); in.close(); } public static void readWithoutBufferedInputStream(String file) throws Exception { // 不用BufferedInputStream读取文件 DataInputStream in = new DataInputStream(new FileInputStream(file)); while (in.available() != 0) in.readByte(); in.close(); } }
运行该程序,其中使用的data.txt文件大小为5.4M,在个人电脑上的输出为:
readWithBufferedInputStream use time:8775 readWithoutBufferedInputStream use time:18487
显然使用了BufferedInputStream效率高了很多。
三、java1.5之后为了方便文件的输入,添加了一个PrintWrite过滤器,它封装了BufferedWriter,并且能够接受String类型的文件名,因此能够精简代码。
import java.io.*; public class FileOutPut { public static void main(String[]args) throws Exception{ BufferedReader in=new BufferedReader(new FileReader("data.txt")); PrintWriter out=new PrintWriter("data1.txt"); String s; long start=System.currentTimeMillis(); while((s=in.readLine())!=null){ out.println(s);//用readLine读取文件时,每一行的回车符会被去掉,因此写入文件的时候要把回车符写回去 } System.out.println("use time:"+(System.currentTimeMillis()-start)); in.close(); out.close(); } }
运行文件同时能够发现,一样是同样大的data.txt文件,读出并写出速度很是快,这个得益于缓存。
四、因为以前的方法往文件里面写入的是字节或字符,没有办法存储一些基本类型,因此要使用DataOutputStream/DataInputStream。
import java.io.*; public class ReadAndWriteBaseType { public static void main(String[] args) throws Exception { DataOutputStream out = new DataOutputStream(new FileOutputStream( "data1.txt")); out.writeUTF("This a String");// 写入字符串要用writeUTF(); out.writeInt(5); out.writeFloat(5.4f); out.close(); DataInputStream in = new DataInputStream(new FileInputStream( "data1.txt")); System.out.println(in.readFloat()); System.out.println(in.readInt()); System.out.println(in.readUTF());// 读出字符串要用readUTF(); in.close(); } }
五、使用RandomAccessFile进行读写文件有点相似DataOutputStream/DataInputStream,都须要指定数据类型。但RandomAccessFile在建立对象的时候须要肯定对文件的操做类型,r/w/rw分别表示只读,只写,读和写。Seek()方法能够处处移动,在文件的任意位置修改内容
import java.io.*; public class UsingRandomAccessFile { public static void main(String[] args) throws Exception { RandomAccessFile rf = new RandomAccessFile("data1.txt", "rw"); rf.writeInt(5); rf.writeInt(10); rf.writeInt(15); rf.writeInt(24); rf.close(); rf = new RandomAccessFile("data1.txt", "r"); System.out.println(rf.readInt()); System.out.println(rf.readInt()); System.out.println(rf.readInt()); System.out.println(rf.readInt()); rf.close(); rf = new RandomAccessFile("data1.txt", "rw"); rf.seek(0);// 把指针指向文件开头 rf.writeInt(-1);// 把前两个字节改为-1 rf.seek(0); System.out.println(rf.readInt()); System.out.println(rf.readInt()); System.out.println(rf.readInt()); System.out.println(rf.readInt()); rf.close(); } }
六、把标准输入用BufferedReader包装并获取键盘输入
public class Systemin { public static void main(String[] args) throws Exception { // System.in为InputStream类型,要经过InputStreamReader将其转换成Reader BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String s; while ((s = in.readLine()) != null) { System.out.println(s); } } }
六、重定向,把控制台输出、错误输出定向到文件,可用来写日志文件
import java.io.*; public class Redirect { public static void main(String[] args) throws Exception { OutputStream console = System.out; PrintStream out = new PrintStream(new BufferedOutputStream( new FileOutputStream("data1.txt"))); BufferedReader in = new BufferedReader(new InputStreamReader( new FileInputStream("data.txt"))); System.setOut(out);// 把输出重定向到out System.setErr(out);// 把错误信息重定向到out String s; while ((s = in.readLine()) != null) System.out.println(s);// 输出被定向到out,因此不会在控制台输出 out.close(); in.close(); } }