Character sets(字符集)
根据sun公司的文档介绍,charset就是一个在16位的unicode编码和另一个编码之间的命名映射。实际上,一个charset让你根据最合适的方式来读写字符。
Java被定义基于unicode编码的,然而,许多人编写代码时都假设一个字符在磁盘上或者在网络流中用一个字节表示。这种假设在许多情况下成立,但是并不是在所有情况下都成立,而且随着计算机变得对Unicode越来越友好,这个假设就日益变得不能成立了。。
这在这一节中,我们将看到如何利用字符集来处理一些文本格式。
Encoders/decoders(编码/解码)
要读写文本,我们就得分别用到字符串的编码和解码器。一个字符不再是代表着一个bit,而是在特定的编码系统下的一个实体。所以,字符在经过特定的编码后才是一种实际的bit串。
一个字符串解码器常备用来将一个字符串按bit的形式映射成实际的字符。相反,一个字符串编码器则是将字符还原成bit。
处理文本的正确方式
我们将来看一个事例程序,UseCharsets.java,这个程序非常简单,他从一个文件中读入一些文本,然后写入到另外的一个文件中,但它将数据当纯文本来处理,直接读入使用了charsetdecoder的charBuffer中,同样的,使用charsetencoder来写入数据。
我们假设存放在磁盘上的文件是以ISO-8859-1格式存储的。实际上,java中支持的编码为:
- US-ASCII
- ISO-8859-1
- UTF-8
- UTF-16BE
- UTF-16LE
- UTF-16
在使用ByteBuffer读入文件数据后,我们需要创建一个ISO-8859-1编码器的一个实例:
Charset latin1 = Charset.forName( "ISO-8859-1" );
然后我们创建一个编码器和解码器。
CharsetDecoder decoder = latin1.newDecoder();
CharsetEncoder encoder = latin1.newEncoder();
为了将我们的byte数据转换成char数据,我们将bytebuffer传入到一个解码器中,返回一个charbuffer。
CharBuffer cb = decoder.decode( bytebuffer );
如果我们需要处理我们的字符,我们可以将字符转换成byte,使用charsetencoder。
ByteBuffer outputData = encoder.decode( cb );
这样转换就完成了,我们可以将数据写回文件。
下面是详细例子:将一个文件从gbk编码转换到utf-8编码。
package com.nio.example;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
public class UseCharacters {
public static void main(String[] args) throws Exception{
Charset gbk = Charset.forName("GBK");
CharsetDecoder decoder = gbk.newDecoder();
Charset utf = Charset.forName("UTF-8");
CharsetEncoder encoder = utf.newEncoder();
FileInputStream fin = new FileInputStream("./src/tx.txt");
FileOutputStream fout = new FileOutputStream("./src/tx_bak.txt");
FileChannel fc = fin.getChannel();
FileChannel fcout = fout.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
CharBuffer charBuffer = CharBuffer.allocate(1024);
while(-1 != fc.read(buffer) ){
buffer.flip();
charBuffer = decoder.decode(buffer);
buffer = encoder.encode(charBuffer);
fcout.write(buffer);
buffer.clear();
}
fcout.close();
fc.close();
fout.close();
fin.close();
}
}