当前位置:首页 » Java基础教程 » Java IO系统

Java IO系统

Java IO系统用法

6. Java IO系统

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)。