为了输出文件中的信息,我们必须每次只读取一个字节的数据,然后将每个byte类型强制转换成char类型。这种方法似乎有点原始--如果我们查看一下java.nio.CharBuffer这个类,将会发现它有一个toString()方法是这样定义的:返回一个包含缓冲器所有字符的字符串。既然ByteBuffer可以看做是具有asCharBuffer()方法的CharBuffer。那么为什么不用它呢?正如下面的输出语句中第一行所见,这种方法并不能解决问题:
public class BufferToText { private static final int BSIZE=1024; public static void main(String[] args) throws Exception{ FileChannel fc=new FileOutputStream("data2.txt").getChannel(); fc.write(ByteBuffer.wrap("Some text".getBytes())); fc.close(); fc=new FileInputStream("data2.txt").getChannel(); ByteBuffer byff=ByteBuffer.allocate(BSIZE); fc.read(byff); byff.flip(); System.out.println(byff.asCharBuffer()); byff.rewind(); String encoding=System.getProperty("file.encoding"); System.out.println("Decode using "+encoding+":"+ Charset.forName(encoding).decode(byff)); fc=new FileOutputStream("data2.txt").getChannel(); fc.write(ByteBuffer.wrap("Some text".getBytes("UTF-16BE"))); fc.close(); fc=new FileInputStream("data.txt").getChannel(); byff.clear(); fc.read(byff); byff.flip(); System.out.println(byff.asCharBuffer()); fc=new FileOutputStream("data2.txt").getChannel(); byff=ByteBuffer.allocate(24); byff.asCharBuffer().put("Some text"); fc.write(byff); fc.close(); fc=new FileInputStream("data2.txt").getChannel(); byff.clear(); fc.read(byff); byff.flip(); System.out.println(byff.asCharBuffer()); } }
缓冲器容纳的是是普通字节,为了把它们转换成字符,我们要么在输入它们的时候对齐进行编码(这样,它们输出时才具有意义),要么在将其从缓冲器输出时进行解码。可以使用java.nio.charset.Charset类实现这些功能,该类提供了把数据编码成多种不同类型字符集的工具:
public class AvailableCharSets { public static void main(String[] args){ SortedMap<String,Charset> charsets=Charset.availableCharsets(); Iterator<String> it=charsets.keySet().iterator(); while (it.hasNext()){ String csName=it.next(); Iterator alias=charsets.get(csName).aliases().iterator(); if(alias.hasNext()){ while (alias.hasNext()){ System.out.println(alias.next()); } } } } }
让我们返回到BufferToText.java,如果我们想对缓冲器调用rewind()(调用该方法是为了返回数据开始部分),接着使用平台默认字符集对数据进行decode(),那么作为结果的CharBuffer可以很好的输出到控制台。可以使用System.getProperty("file.encoding")发现默认字符集,它会产生代表字符集名称的字符串。把该字符串传送给Charset.forName()用以产生Charset对象,可以用他对字符串进行解码。
另一选择是在读文件时,使用能够产生打印的输出的字符集进行encode().。正如在BufferToText.java中第3部分那样。这里,UTF-16BE可以把文本写到文件中,当读取时,我们只需要把他转换成CharBuffer,就会产生所期望的文本。