JDK1.0输入流
InputStream |
ByteArrayInputStream |
FileInputStream |
FilterInputStream |
ObjectInputStream |
PipedInputStream |
SequenceInputStream |
|
BufferedInputStream |
DataInputStream |
PushbackInputStream |
LineNumberInputStream |
JDK1.1输入流
Reader |
BufferedReader |
FilterReader |
PipedReader |
StringReader |
InputStreamReader |
CharArrayReader |
FileReader |
PushbackReader |
LineNumberReader |
JDK1.0输出流
OutputStream |
BufferedOutputStream |
DataOutputStream |
PrintStream |
ByteArrayOutputStream |
FileOutputStream |
FilterOutputStream |
ObjectOutputStream |
PipedOutputStream |
JDK1.1输出流
Writer |
BufferedWriter |
FilterWriter |
PipedWriter |
StringWriter |
FileWriter |
PrintWriter |
OutputStreamWriter |
CharArrayWriter
|
如果你刚刚接触Java的IO部分, 你可能会感觉无从入手, 确实Java提供了过多的类,反而让人感到很乱。
可将Java库的IO类分为输入与输出两个部分, 在1.0版本中提供了两个抽象基类, 所有输入的类都从InputStream继承, 所有输出的类都从OutputStream继承, 1.1提供了两个新的基类, 负责输入的Reader与输出的Writer, 但它们并不是用来替换原来老的InputStream与OutputStream, 它们主要是让Java能更好的支持国际化的需求。 原来老的IO流层只支持8位字节流, 不能很好地控制16位Unicode字符。 Java内含的char是16位的Unicode, 所以添加了Reader和Writer层次以提供对所有IO操作中的Unicode的支持。 除此之外新库也对速度进行了优化, 可比旧库更快地运行。
InputStream的类型:
1. 字节数组
2. String对象
3. 文件
4. 管道, 可以从另外一个输出流得到一个输入流
5. 一系列的其他流, 可以将这些流统一收集到单独的一个流内。
6. 其他起源(如socket流等)
还有一个是File类, Java中一个目录也是一个文件,可以用file.isFile()和file.isDirectory()来进行判断是文件还是目录。 File 对象可能作为参数转换为文件流进行操作。 具体操作参照Java IO API。
常用方法:
/**
* 拼文件名, 在windows(\)跟unix(/)上的文件分割符是不一样的
* 可以通过File类的静态成员变量separator取得
*/
public static String concatFileName(String dir, String fileName) {
String fullFileName = "";
if (dir.endsWith(File.separator)) {fullFileName = dir + fileName;
} else {fullFileName = dir + File.separator + fileName;}
return fullFileName; }
/**
* 从控制台读取输入的数据, System.in (InputStream) 先转换至InputStreamReader再用
* BufferedReader进行读取.
*
*/
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String str = "";
while (str != null) {str = in.readLine();// process(str); }
/**
* 从文件中按行进行读取数据处理
*/
BufferedReader in = new BufferedReader(new FileReader("infilename"));
String str;
while ((str = in.readLine()) != null) {// process(str); }
in.close();
/**
* 写数据至一个新的文件中去.
*/
BufferedWriter out = new BufferedWriter(new FileWriter("outfilename"));
out.write("a String");
out.close();
/**
* 追加新的数据到一个文件中去, 如果原文件不存在
* 则新建这个文件.
*/
BufferedWriter out = new BufferedWriter(new FileWriter("filename", true));
out.write("aString");
out.close();
/**
* 将一个可序列化的Java的object以流方式写到一个文件中去中.
*/
ObjectOutput out = new ObjectOutputStream(new FileOutputStream("filename.ser"));
out.writeObject(object);
out.close();
/**
* 从文件中恢复序列化过的Java Object
*/
ObjectInputStream in = new ObjectInputStream(new FileInputStream("filename.ser"));
Object object = (Object) in.readObject();
in.close();
/**
* 以指定的编码方式从文件中读取数据
*/
BufferedReader in = new BufferedReader(new InputStreamReader(
new FileInputStream("infilename"), "UTF8"));
String str = in.readLine();
/**
* 以指定的编码方式写数据到文件中
*/
Writer out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("outfilename"), "UTF8"));
out.write("a String");
out.close();
由上面的例子可以看出, 流之间可以互相转换, 如果想对流进行字符操作最好将之转换成BufferedReader与BufferedWriter这样可以提高读写的效率。
需要注意的是一般来说流的大小是得不到的, 虽然一般的InputStream都有一个available()的方法可以返回这个流可以读到的字节数, 不过这个方法有时候不会很准确, 比如在读取网络传输的流的时候, 取到的长度并不一定是真实有效的长度。
大家在写程序的时候可能已经注意到一些类都继承了java.io.Serializable这个接口, 其实继承了这个接口之后这个类的本身并不做任何事情, 只是这个类可以被序列化并通过流来进行传输, 并可被还原成原Object。 这个流可以通过网络传输(EJB 中进行传递参数和返回值的Data Class), 也可以保存到文件中去(ObjectOutputStream)。