在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());
}
}
}