NIO-字符集

作者: 甚了 | 来源:发表于2016-11-25 18:24 被阅读21次

字符集

根据 Sun 的文档,一个 Charset 是“十六位 Unicode 字符序列与字节序列之间的一个命名的映射”。实际上,一个 Charset 允许您以尽可能最具可移植性的方式读写字符序列。

Java 语言被定义为基于 Unicode。然而在实际上,许多人编写代码时都假设一个字符在磁盘上或者在网络流中用一个字节表示。这种假设在许多情况下成立,但是并不是在所有情况下都成立,而且随着计算机变得对 Unicode 越来越友好,这个假设就日益变得不能成立了。


编码/解码

要读和写文本,我们要分别使用 CharsetDecoder 和 CharsetEncoder。将它们称为 解码器 和 编码器 是有道理的。

一个 字符 不再表示一个特定的位模式,而是表示字符系统中的一个实体。因此,由某个实际的位模式表示的字符必须以某种特定的 编码 来表示。

CharsetDecoder 用于将逐位表示的一串字符转换为具体的 char 值。同样,一个 CharsetEncoder 用于将字符转换回位。

处理文本的正确方式

现在我们将分析这样一个程序。这个程序非常简单 ― 它从一个文件中读取一些文本,并将该文本写入另一个文件。但是它把该数据当作文本数据,并使用 CharBuffer 来将该数句读入一个 CharsetDecoder 中。同样,它使用 CharsetEncoder 来写回该数据。

我们将假设字符以 GBK 字符集的形式储存在磁盘上。尽管我们必须为使用 Unicode 做好准备,但是也必须认识到不同的文件是以不同的格式储存的,而 ASCII 无疑是非常普遍的一种格式。事实上,每种 Java 实现都要求对以下字符编码提供完全的支持:

  • GBK
  • GB2312
  • US-ASCII
  • ISO-8859-1
  • UTF-8
  • UTF-16BE
  • UTF-16LE
  • UTF-16

在打开相应的文件、将输入数据读入名为 inputData 的 ByteBuffer 之后,我们的程序必须创建 GBK 字符集的一个实例:

Charset gbk = Charset.forName( "GBK" );

然后,创建一个解码器(用于读取)和一个编码器 (用于写入):

CharsetDecoder decoder = gbk.newDecoder();
CharsetEncoder encoder = gbk.newEncoder();

为了将字节数据解码为一组字符,我们把 ByteBuffer 传递给 CharsetDecoder,结果得到一个 CharBuffer:

CharBuffer cb = decoder.decode( inputData );

如果想要处理字符,我们可以在程序的此处进行。但是我们只想无改变地将它写回,所以没有什么要做的。
要写回数据,我们必须使用 CharsetEncoder 将它转换回字节:

ByteBuffer outputData = encoder.encode( cb );

在转换完成之后,我们就可以将数据写到文件中了。


场景描述:

我们要将一个GBK编码的文件(gbk.txt)转存到一个UTF编码的文件(utf.txt)中。

  • 我们的gbk.txt文件是一个 ‘GBK’编码保存的文件文件中有一段中文:
10 个中文字符+2个换行符
  • 使用Charset 对GBK文件进行GBK解码,然后再进行UTF编码保存,代码如下
    @Test
    public void charsetTest() {
        try {
            FileInputStream fin = new FileInputStream("/Users/dongsj/workspace/dsj/javaSpace/nettyDemo/src/test/resources/nio/gbk.txt");
            FileChannel fileChannel = fin.getChannel();
            ByteBuffer inputData = ByteBuffer.allocate(1024);
            int result = fileChannel.read(inputData);
            inputData.flip();  // !!!

            System.out.println("Read result : " + result);


            Charset gbk = Charset.forName("GBK");
            Charset utf = Charset.forName("UTF-8");

            CharsetDecoder gbkDecoder = gbk.newDecoder();   // gbk解码器
            //CharsetEncoder gbkEncoder = gbk.newEncoder(); // gbk编码器
            CharsetEncoder utfEncoder = utf.newEncoder();   // utf编码器

            CharBuffer charBuffer = gbkDecoder.decode(inputData);
            //ByteBuffer outputBuffer = gbkEncoder.encode(charBuffer);  // 使用gbk编码
            ByteBuffer outputBuffer = utfEncoder.encode(charBuffer);    // 使用utf编码

            FileOutputStream fout = new FileOutputStream("/Users/dongsj/workspace/dsj/javaSpace/nettyDemo/src/test/resources/nio/utf.txt");
            FileChannel channelout = fout.getChannel();

            result = channelout.write(outputBuffer);
            System.out.println("Write result : " + result);

        } catch (CharacterCodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  • 结果
UTF文件 字节数
  • 如果依然采用GBK编码保存的话,结果一定是乱码,毕竟是中文
乱码

相关文章

  • NIO-字符集

    字符集 根据 Sun 的文档,一个 Charset 是“十六位 Unicode 字符序列与字节序列之间的一个命名的...

  • 网络编程-NIO 理论部分

    NIO- no_block IO 或者叫NewIO JAVA 1.4引入的 1 、NIO和BIO的区别 1....

  • NIO-读写

    NIO 读写 Github Demo 读和写是 I/O 的基本过程。从一个通道中读取很简单:只需创建一个缓冲区,然...

  • NIO-简介

    NIO Github Demo NIO简介: I/O(输入/输出):指的是计算机与外部世界或者一个程序与计算机的其...

  • NIO-简介

    本文作者:杨龙,叩丁狼高级讲师。原创文章,转载请注明出处。 IO 操作问题 在 Java 的早期,JVM 在解释字...

  • 2019-04-16字符集 通配符

    修改字符集 永久修改字符集 重启xshell 原因 与远程工具不同字符集 排错 查看xshll字符集查看系统字符集...

  • 字符集与校对规则

    MySQL字符集及校对规则的理解 阅读目录:MySQL的字符集和校对规则 MySQL的字符集 MySQL与字符集 ...

  • MYSQL 8 基本操作之03 (字符集)

    查询服务器字符集 查询服务器字符集校对规则 查询数据库字符集 查询数据库字符集校对规则 查询表的字符集及校对规则

  • 字符集和字符编码

    常常会把字符集和字符编码混起来。下面是一些常用的字符集:ASCII字符集GB2312字符集GBK字符集GB1803...

  • NIO-异步IO

    异步I/O Github Demo 连网是学习异步 I/O 的很好基础,而异步 I/O 对于在 Java 语言中执...

网友评论

    本文标题:NIO-字符集

    本文链接:https://www.haomeiwen.com/subject/vrrwpttx.html