如果你刚刚接触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)。