🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
<!-- Converting Data --> ## 数据转换 为了将 **GetChannel.java** 文件中的信息打印出来。在 Java 中,我们每次提取一个字节的数据并将其转换为字符。看起来很简单 —— 如果你有看过 `ava.nio.`**CharBuffer** 类,你会发现一个 `toString()` 方法。该方法的作用是“返回一个包含此缓冲区字符的字符串”。 既然 **ByteBuffer** 可以通过 **CharBuffer** 类的 `asCharBuffer()` 方法查看,那我们就来尝试一样。从下面输出语句的第一行可以看出,这并不正确: ```java // newio/BufferToText.java // (c)2017 MindView LLC: see Copyright.txt // 我们无法保证该代码是否适用于其他用途。 // 访问 http://OnJava8.com 了解更多本书信息。 // text 和 ByteBuffers 互转 import java.nio.*; import java.nio.channels.*; import java.nio.charset.*; import java.io.*; public class BufferToText { private static final int BSIZE = 1024; public static void main(String[] args) { try( FileChannel fc = new FileOutputStream( "data2.txt").getChannel() ) { fc.write(ByteBuffer.wrap("Some text".getBytes())); } catch(IOException e) { throw new RuntimeException(e); } ByteBuffer buff = ByteBuffer.allocate(BSIZE); try( FileChannel fc = new FileInputStream( "data2.txt").getChannel() ) { fc.read(buff); } catch(IOException e) { throw new RuntimeException(e); } buff.flip(); // 无法运行 System.out.println(buff.asCharBuffer()); // 使用默认系统默认编码解码 buff.rewind(); String encoding = System.getProperty("file.encoding"); System.out.println("Decoded using " + encoding + ": " + Charset.forName(encoding).decode(buff)); // 编码和打印 try( FileChannel fc = new FileOutputStream( "data2.txt").getChannel() ) { fc.write(ByteBuffer.wrap( "Some text".getBytes("UTF-16BE"))); } catch(IOException e) { throw new RuntimeException(e); } // 尝试再次读取: buff.clear(); try( FileChannel fc = new FileInputStream( "data2.txt").getChannel() ) { fc.read(buff); } catch(IOException e) { throw new RuntimeException(e); } buff.flip(); System.out.println(buff.asCharBuffer()); // 通过 CharBuffer 写入: buff = ByteBuffer.allocate(24); buff.asCharBuffer().put("Some text"); try( FileChannel fc = new FileOutputStream( "data2.txt").getChannel() ) { fc.write(buff); } catch(IOException e) { throw new RuntimeException(e); } // 读取和显示: buff.clear(); try( FileChannel fc = new FileInputStream( "data2.txt").getChannel() ) { fc.read(buff); } catch(IOException e) { throw new RuntimeException(e); } buff.flip(); System.out.println(buff.asCharBuffer()); } } ``` 输出结果: ``` ???? Decoded using windows-1252: Some text Some text Some textNULNULNUL ``` 缓冲区包含普通字节,为了将这些字节转换为字符,我们必须在输入时对它们进行编码(这样它们输出时就有意义了),或者在输出时对它们进行解码。我们可以使用 `java.nio.charset.`**Charset** 字符集工具类来完成。代码示例: ```java // newio/AvailableCharSets.java // (c)2017 MindView LLC: see Copyright.txt // 我们无法保证该代码是否适用于其他用途。 // 访问 http://OnJava8.com 了解更多本书信息。 // 展示 Charsets 和 aliases import java.nio.charset.*; import java.util.*; public class AvailableCharSets { public static void main(String[] args) { SortedMap<String,Charset> charSets = Charset.availableCharsets(); for(String csName : charSets.keySet()) { System.out.print(csName); Iterator aliases = charSets.get(csName) .aliases().iterator(); if(aliases.hasNext()) System.out.print(": "); while(aliases.hasNext()) { System.out.print(aliases.next()); if(aliases.hasNext()) System.out.print(", "); } System.out.println(); } } } ``` 输出结果: ``` Big5: csBig5 Big5-HKSCS: big5-hkscs, big5hk, Big5_HKSCS, big5hkscs CESU-8: CESU8, csCESU-8 EUC-JP: csEUCPkdFmtjapanese, x-euc-jp, eucjis, Extended_UNIX_Code_Packed_Format_for_Japanese, euc_jp, eucjp, x-eucjp EUC-KR: ksc5601-1987, csEUCKR, ksc5601_1987, ksc5601, 5601, euc_kr, ksc_5601, ks_c_5601-1987, euckr GB18030: gb18030-2000 GB2312: gb2312, euc-cn, x-EUC-CN, euccn, EUC_CN, gb2312-80, gb2312-1980 ... ``` 回到 **BufferToText.java** 中,如果你 `rewind()` 缓冲区(回到数据的开头),使用该平台的默认字符集 `decode()` 数据,那么生成的 **CharBuffer** 数据将在控制台上正常显示。可以通过 `System.getProperty(“file.encoding”)` 方法来查看平台默认字符集名称。传递该名称参数到 `Charset.forName()` 方法可以生成对应的 `Charset` 对象用于解码字符串。 另一种方法是使用字符集 `encode()` 方法,该字符集在读取文件时生成可打印的内容,如你在 **BufferToText.java** 的第三部分中所看到的。上例中,**UTF-16BE** 被用于将文本写入文件,当文本被读取时,你所要做的就是将其转换为 **CharBuffer**,并生成预期的文本。 最后,如果将 **CharBuffer** 写入 **ByteBuffer**,你会看到发生了什么(更多详情,稍后了解)。**注意**,为 **ByteBuffer** 分配了24个字节,按照每个字符占用 2 个自字节, 12 个字符的空间已经足够了。由于“some text”只有 9 个字符,受其 `toString()` 方法影响,剩下的 0 字节部分也出现在了 **CharBuffer** 的展示中,如输出所示。