在JAVA IO包下面, 包含了3类文件工具. 字节流工具, 字符流工具和文件对象工具. 当然除去对文件的操作外,还有各种对数据的读写工具. 数据流可以是网络数据,文件数据,键盘输入数据,数据库BLOB,CLOB数据,等等. 这篇文章只讲如何操做文件数据. 后续会写NIO.
流包含字节流(Byte Stream)和字符流(Char Stream). Byte Stream皆起源与InputStream和OutputStream. Char Stream皆起源与Reader和Writer. 字符和字节的区别是,字符是字符集中一个有意义的字符单元. 而字节只是一个8bit二进制数据.
字节流最原始的方法是InputStream的read()和OutputStream的write(). 分别为读取一个字节和写入一个字节. 在InputStream和OutputStream之上,包装了很多字节流工具,来一次性的读或者写多个字符. 但无论如何调用什么方法,最终包装过的方法都是通过调用最原始的read()和write()来操作流.
字符流最原始的方法是Reader的read()和Writer的write()方法.分别为读取一个字符或写入一个字符.同上,包装的字符流工具最终也是在和原始的read()和write()在打交道.
下面的Code example包含了各种对文件的读写方法.使用到了FileInputStream, FileOutputStream, InputStreamReader, OutputStreamWriter, PrintWriter, BufferedReader, File, ClassLoader.
为什么没有使用到FileReader和FileWriter? 因为FileReader和FileWriter无法声明字符集编码, 它们只使用系统默认的字符集. 它的做法是向系统中以不同编码写入文件然后再读取出来,以获取系统正确的字符集.
为什么使用了BufferedReader,但没有使用与之对称的BufferedWriter? 因为BufferedReader可以readLine(), 但BufferedWriter只能write(String, int, int)和newLine(). 从Java1.5以后加入了PrintWriter,它提供了更方便的类似于System.out的书写方法.
为什么还提到了ClassLoader? 在读写external文件的时候,使用绝对或者相对路径来定位文件位置,然后使用InputStream来读入文件字节流.如果读取的文件是在classpath中,比如一个.class文件,一个.xml配置文件或者一个.properties文件.都应该使用ClassLoader.getResouceAsStream()或者class.getResourceAsStream()来读如文件字节流.
ClassLoader.getResource与class.getResource又有什么区别呢? 其实,class.getResource()调用的是ClassLoader.getResource(). 只是两者对参数的定义不同. ClassLoader.getResource()需要的参数是完整路径.比如"com/ibm/test/log.properties". 而Logger.class.getResource()所需要的参数有两种,一个是不以"/"开头的路径,比如"log.properties",意为在Logger.class同级目录下寻找log.properties. 另一个参数是以"/"开头的路径,指的是在classpath中寻找.比如"/com/ibm/test/log.properties".
File与流工具区别是? File是文件对象,只是用于访问文件属性的工具.读写文件,需要用流工具.
在运行下面的代码的时候,请把产生文件的路径加入classpath中.
public class FileTest { private static String[] article = {"第一行是英文: Holle joey.", "第二行是中文: 你好, joey.", "第三行是特殊字符:孇"}; public static void main(String[] args) throws IOException { createFile("1.txt", "utf-16"); readFile("1.txt"); readFileByClassLoader("1.txt"); binaryCopy("1.txt", "2.txt"); characterCopy("1.txt", "utf-16", "3.txt", "gbk"); lineCopy("1.txt", "utf-16", "4.txt", "utf-8"); printFileInfo(new String[]{"1.txt", "2.txt","3.txt","4.txt","5.txt"}); } private static void readFile(String path) throws IOException { BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(new FileInputStream(path), "utf-16")); String line; while ((line = br.readLine())!=null) { System.out.println(line); } } catch (Exception e) { e.printStackTrace(); } finally { if (br != null) br.close(); } } private static void readFileByClassLoader(String path) throws IOException { BufferedReader br = null; try { InputStream in = FileTest.class.getClassLoader().getResourceAsStream(path); // or use below // InputStream in = FileTest.class.getResourceAsStream("/"+path); br = new BufferedReader(new InputStreamReader(in, "utf-16")); String line; while ((line = br.readLine())!=null) { System.out.println(line); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } finally { if (br != null) br.close(); } } private static File createFile(String name, String charsetName) throws FileNotFoundException, UnsupportedEncodingException { PrintWriter writer=null; try { writer = new PrintWriter(name,charsetName); for (int i=0; i< article.length; i++) writer.println(article[i]); } finally { if (writer !=null) writer.close(); } File file = new File(name); if (!file.exists()) { throw new FileNotFoundException(name); } return file; } private static boolean binaryCopy(String source, String target) throws IOException { FileInputStream in = null; FileOutputStream out = null; try { in = new FileInputStream(source); out = new FileOutputStream(target); int _byte; while ((_byte = in.read()) != -1) { out.write(_byte); } return true; } catch (Exception e) { e.printStackTrace(); return false; } finally { if (in!=null) in.close(); if (out!=null) out.close(); } } private static boolean characterCopy(String source, String sourceCSN, String target, String targetCSN) throws IOException { InputStreamReader in = null; OutputStreamWriter out = null; try { in = new InputStreamReader(new FileInputStream(source), sourceCSN); out = new OutputStreamWriter(new FileOutputStream(target), targetCSN); int _char; while((_char = in.read()) != -1) { out.write(_char); } return true; } catch (Exception e) { e.printStackTrace(); return false; } finally { if (in!=null) in.close(); if (out!=null) out.close(); } } private static boolean lineCopy(String source, String sourceCSN, String target, String targetCSN) throws IOException { BufferedReader in = null; PrintWriter out = null; try { in = new BufferedReader(new InputStreamReader(new FileInputStream(source), sourceCSN)); out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(target), targetCSN)); String line; while((line = in.readLine()) != null) { out.println(line); } return true; } catch (Exception e) { e.printStackTrace(); return false; } finally { if (in!=null) in.close(); if (out!=null) out.close(); } } private static void printFileInfo(String[] fileNames) { for (String filename : fileNames) { File file = new File(filename); StringBuffer info = new StringBuffer(); info.append("Name:").append(file.getName()).append("\n") .append("Path:").append(file.getAbsolutePath()).append("\n") .append("Size:").append(file.length()).append("\n"); System.out.println(info.toString()); } } }