通过在java中使用UTF-8字符集输出流将UTF-16字符写入文件,但文件中的结果数据仍为UTF-16。为什么?

时间:2015-04-14 00:43:20

标签: java unicode encoding utf-8 character-encoding

创建一个简单的java程序,看看utf 8 charset是否可以保存utf16字符,并且它能够保存它。为什么? 如果UTF-08可以保存UTF-16字符而不是使用UTF-16和UTF-8的差异。

两个测试字符的unicode值都超出了UTF-8范围,即256。

✈unicode值:9992
❄unicode值:10052

请参阅示例程序: -

import java.io.*;
import java.nio.charset.Charset;

public class UTFSizeTest {

    public static void main(String[] args) throws IOException {
        System.out.println("Default Charset=" + Charset.defaultCharset());
        write("UTF-16");
        write("UTF-8");
        write(null);
    }

    private static void write(String utf) throws IOException {
        final String fileName = "someFile" + utf;

        Writer writer;

        if (utf == null) {
            writer = new OutputStreamWriter(new FileOutputStream(fileName));
        } else {
            writer = new OutputStreamWriter(new FileOutputStream(fileName), utf);
        }


        for (int i = 0; i < 2; i++) {
            writer.write("✈ ❄");
            writer.write("\n");
        }

        writer.close();

        System.out.println(fileName + " size: "+ new File(fileName).length());
    }
}

使用utf-16和utf-8在两个文件上写入相同的数据: - ✈❄
✈❄

对于UTF-16和UTF-8,文件大小也几乎与控制台输出上的大小相同。
控制台输出如下: -
默认字符集= UTF-8
someFileUTF-16尺寸:18
someFileUTF-8尺寸:16
someFilenull大小:16

如果utf-08可以节省16位unicode就好了,为什么要在java中使用uff-16。

谢谢。

2 个答案:

答案 0 :(得分:3)

  

创建一个简单的java程序,看看utf 8 charset是否可以保存utf16字符

它可以。 UTF-8和UTF-16只是相同Unicode字符集的不同编码。这两种编码都旨在支持所有Unicode代码点,无论是现在还是可预见的未来。

  

它能够保存它。为什么呢?

因为它们都支持相同的Unicode代码点。根据设计,在各种UTF之间进行转换是一种无损操作。

  

如果UTF-08可以保存UTF-16字符而不是使用UTF-16和UTF-8的差异。

UTF-8主要优于UTF-16,因为:

  1. UTF-8向后兼容7bit ASCII,因此可以将许多遗留代码迁移到UTF-8而不会中断。

  2. 对于大多数语言,特别是基于拉丁语的语言,UTF-8比UTF-16更紧凑,从而节省了内存,磁盘空间和带宽。但是,有些情况,主要是亚洲语言,还有符号(如你的例子),其中UTF-16实际上比UTF-8更紧凑。

  3.   

    请参阅示例程序: -
      ...
      使用utf-16和utf-8在两个文件上写入相同的数据: -

    是的,他们表示相同的Unicode代码点,因此通过支持Unicode的文本查看器/编辑器呈现相同。但它们的物理字节非常不同:

    ✈
    UTF-8:    e2 9c 88
    UTF-16LE: 08 27
    UTF-16BE: 27 08
    
    ❄
    UTF-8:    e2 9d 84
    UTF-16LE: 44 27
    UTF-16BE: 27 44
    
      

    对于UTF-16和UTF-8,文件大小也几乎与控制台输出上的大小相同。

    在上面的示例中,您选择了2个Unicode代码点,这些代码点不需要UTF-16代理对来对它们进行编码,因此它们在UTF-16中使用2个字节而不是4个字节。在UTF-8中,每个占用3个字节,但大小差异减少了它们之间的1字节U+0020 SPACE字符。尝试使用较高和较低代码点值的较大混合编写较长的字符串,您应该会看到文件大小的更大变化。

      

    如果utf-08可以节省16位unicode就好了,为什么要在java中使用uff-16。

    虽然UTF-8和UTF-16都是可变长度编码,但UTF-16的长度往往比UTF-8少。 UTF-8的1字节,2字节和3字节格式的所有代码点都符合UTF-16的2字节格式,使UTF-16更接近固定长度而不是UTF-8 。这也意味着UTF-16更容易向前搜索,特别是向后搜索,你只需要为每个代码点跳2或4个字节,而使用UTF-8你必须每跳1个,2个,3个或4个字节。代码点,因此UTF-8中的解码逻辑比UTF-16更复杂。

    请记住,当Java,Windows等采用Unicode时,它存在于UTF-16之前,当时所有可用的代码点都很容易适应UCS-2,这是一种固定长度的编码。直到后来才开始使用UCS-2和UTF-16来取代它。到那时,重新编写已迁移到Unicode的代码为时已晚,因此UTF-16必须保持与UCS-2的向后兼容性。此外,现实世界中使用的大量Unicode数据仍然适合UCS-2,只有更高的代码点才真正需要用于编码UTF-16代理的额外字节。

    因此,这通常使UTF-16成为处理数据的更合适的选择。至少在处理非ASCII字符时,这是在内存使用和处理开销之间比UTF-8更好的折衷。但是UTF-8向后兼容ASCII,它往往是一种更适合存储和交换数据的格式。

答案 1 :(得分:0)

由于我的无知,我问了这个问题。 我虽然UTF-8只能保存8位字符点,但Unicode或Unicode字符需要UTF-16意味着字符由2个字节或16位表示。

但在阅读了一些论坛后,我意识到UTF-8,UTF-16和UTF-32都是Unicode字符的不同编码样式,实际上UTF-8可以代表最多6字节/ 48位的字符。 / p>

感谢