读写文本文件
早些时候曾提到从文件里面读取字符的方法调用的消耗可能是重大的。这个问题在计算文本文件的行数的另一个例子中也可以找到。:
import java.io.*;
public class line1 {
public static void main(String args[]) {
if (args.length != 1) {
System.err.println("missing filename");
System.exit(1);
}
try {
FileInputStream fis = new FileInputStream(args[0]);
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
int cnt = 0;
while (dis.readLine() != null)
cnt++;
dis.close();
System.out.println(cnt);
} catch (IOException e) {
System.err.println(e);
}
}
}这个程序使用老的DataInputStream.readLine 方法,该方法是使用用读取每个字符的 read 方法实现的。一个新方法是:
import java.io.*;
public class line2 {
public static void main(String args[]) {
if (args.length != 1) {
System.err.println("missing filename");
System.exit(1);
}
try {
FileReader fr = new FileReader(args[0]);
BufferedReader br = new BufferedReader(fr);
int cnt = 0;
while (br.readLine() != null)
cnt++;
br.close();
System.out.println(cnt);
} catch (IOException e) {
System.err.println(e);
}
}
}这个方法更快。例如在一个有200,000行的 6 MB文本文件上,第二个程序比第一个快大约20%。
但是即使第二个程序不是更快的,第一个程序依然有一个重要的问题要注意。第一个程序在JavaTM 2编译器下引起了不赞成警告,因为DataInputStream.readLine太陈旧了。它不能恰当的将字节转换为字符,因此在操作包含非ASCII字符的文本文件时可能是不合适的选择。(Java语言使用Unicode字符集而不是ASCII)
这就是早些时候提到的字节流和字符流之间的区别。像这样的一个程序:
import java.io.*;
public class conv1 {
public static void main(String args[]) {
try {
FileOutputStream fos = new FileOutputStream("out1");
PrintStream ps = new PrintStream(fos);
ps.println("\uffff\u4321\u1234");
ps.close();
} catch (IOException e) {
System.err.println(e);
}
}
}向一个文件里面写,但是没有保存实际的Unicode字符输出。Reader/Writer I/O 类是基于字符的,被设计用来解决这个问题。OutputStreamWriter 应用于字节编码的字符。
一个使用PrintWriter写入Unicode字符的程序是这样的:
import java.io.*;
public class conv2 {
public static void main(String args[]) {
try {
FileOutputStream fos = new FileOutputStream("out2");
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8");
PrintWriter pw = new PrintWriter(osw);
pw.println("\uffff\u4321\u1234");
pw.close();
} catch (IOException e) {
System.err.println(e);
}
}
}
这个程序使用UTF8编码,具有ASCII文本是本身而其他字符是两个或三个字节的特性。