深入浅出Java中文问题——文件读写【转】
前段时间写的深入浅出Java中文问题系列描述了很多Java各种应用中出现的中文问题,唯独没有说到文件的读写。最近用Java处理文件的时候,同样遇到了中文问题,觉得还是有必要总结一下,也使该系列的文章更加完整。
熟悉Java 的人都知道,在Java中,IO是分成两大部分的,分别对应字节和字符的操作,也就是Stream和Character,它们之间可以相互转换,桥梁就是StreamInputReader/StreamOutputWriter。为了更加清楚的了解它们之间的关系,我们可以看看它们所在的类结构。
- java.io.InputStream (implements java.io.Closeable)
- java.io.OutputStream (implements java.io.Closeable, java.io.Flushable)
- java.io.RandomAccessFile (implements java.io.Closeable, java.io.DataInput, java.io.DataOutput)
- java.io.Reader (implements java.io.Closeable, java.lang.Readable)
- java.io.BufferedReader
- java.io.InputStreamReader
- java.io.FileReade
- java.io.Writer (implements java.lang.Appendable, java.io.Closeable, java.io.Flushable)
- java.io.BufferedWriter
- java.io.OutputStreamWriter
- java.io.FileWriter
上面列出来的并不是Java.io中全部的类,但是对于文件读写来说已经足够了。通常,我们使用以下代码来进行文件的读写:
FileWriter fw = new FileWriter("test.txt");
fw.write("中文你好");
fw.close();
}
public String naiveRead() throws IOException{
FileReader fr = new FileReader("test.txt");
BufferedReader br = new BufferedReader(fr);
String str = br.readLine();
br.close();
fr.close();
return str;
}
如果我们的是中文平台,上面代码是可以正常运行的。但是如果我们把这些代码放到一个ISO8859-1的系统上,中文问题就出来了(当然,前提你在javac的时指定了编码方式,如javac -encoding gb2312 ***.java,参看该系列前面的文章)。为什么呢?这是因为FileWriter和FileReader是辅助类,为了方便大家使用 OutputSteamWriterer 和 InputStreamReader 而屏蔽了字符集的设定操作,而采用系统默认的编码方式,而这在很多情况下也能满足用户的需求。在中文系统中,系统的默认编码方式一般是GBK,因此文件中中文的读写是没有问题的。但是,当程序运行在ISO8859-1的系统中时,JVM使用ISO8859-1对中文进行编码,当然就认不到了,于是那一个个的问号就来了。
那怎么办呢?既然捷径走不通,我们就只好使用OutputSteamWriter 和 InputStreamReader了。
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("test.txt"), "utf-8");
osw.write("中国万岁");
osw.close();
}
public String read() throws IOException{
InputStreamReader isr = new InputStreamReader(
new FileInputStream("test.txt"),"utf-8");
BufferedReader br = new BufferedReader(isr);
String str = br.readLine();
br.close();
isr.close();
return str;
}
在处理文件的过程中,我们还会用到RandomAccessFile这个类来随机访问文件。这里,如果我们写入字符串的时候调用writeChars,那么,如果写入的是中文,中文问题就又会出现了。因为此时RandomAccessFile并没有使用系统的默认编码来写入文件,而是直接将内存中的二进制数据直接写到文件中去。如何解决这个问题呢?只要读写对称就行了。
RandomAccessFile raf = new RandomAccessFile("test1.txt","rw");
raf.writeChars("中国你好");
raf.close();
}
public String randRead() throws IOException{
RandomAccessFile raf = new RandomAccessFile("test1.txt","r");
StringBuffer sb = new StringBuffer();
while( raf.getFilePointer() < raf.length()){
sb.append( raf.readChar() );
}
raf.close();
return sb.toString();
}
RandomAccessFile raf = new RandomAccessFile("test1.txt","rw");
raf.writeUTF("中国你好");
raf.close();
}
public String randRead() throws Exception{
RandomAccessFile raf = new RandomAccessFile("test1.txt","r");
String str = raf.readUTF();
raf.close();
return str;
}

没有评论:
发表评论