Har*_* K. 1 c unicode utf-8 utf-16 libiconv
有大量关于 Unicode 代码单元、代码点等的信息,但我对使用字节流(libiconv需要)转换组合字符、字素等仍然有点模糊。
目前我只对使用 libconv 的 UTF-8/UTF-16/UTF-32 之间的转换感兴趣iconv(),它期望源缓冲区和目标缓冲区的字节长度作为参数。
问题:是否有一种安全的方法可以根据源缓冲区的已知字节长度快速计算目标缓冲区的最大可能字节长度?
比方说,例如,使用已知(如果有的话,不包括 0x0000 终止)从u16buf到转换。在最坏的情况下,UTF-16 源缓冲区中的每个代码点将有 1 个两字节单元,对应于 UTF-8 目标缓冲区中每个代码点的 4 个单字节单元。这足以安全地假设 UTF-8 目标缓冲区永远不会超过?u8bufu16byteslen2 * u16lenbytes
我实际上已经尝试过并且似乎有效,但我不确定我是否遗漏了涉及组合字符和字素簇的极端情况。我的怀疑来自于我对这些东西如何在这 3 种不同编码之间转换的无知。我的意思是,字素是否可能需要说 3 个 UTF-16 代码点,但在转换时需要 10 个 UTF-8 代码点?
在这种情况下,翻倍u16lenbytes是不够的,对吧?如果是这样,有没有其他直接的方法来预先计算目标缓冲区的最大长度?
问题:是否有一种安全的方法可以根据源缓冲区的已知字节长度快速计算目标缓冲区的最大可能字节长度?
是的。
| 到 UTF-8 | 到 UTF-16 | 到 UTF-32 | |
|---|---|---|---|
| 来自 UTF-8 | ×2 | ×4 | |
| 来自 UTF-16 | ×1 ½ | ×1 | |
| 来自 UTF-32 | ×1 | ×1 |
您可以通过按代码点范围将其分解来自己计算。选择一个源列和目标列,并找到最大的比率。
| 代码点 | UTF-8 长度 | UTF-16 长度 | UTF-32 长度 |
|---|---|---|---|
| 0000…007F | 1 | 2 | 4 |
| 0080…07FF | 2 | 2 | 4 |
| 0800…FFFF | 3 | 2 | 4 |
| 10000…10FFFF | 4 | 4 | 4 |
组合字符和字素簇不会产生任何影响。编码只是将一系列Unicode 标量值转换为字节,并且非常简单。
请注意,转换为 UTF-16 时需要添加两个额外字节,转换为 UTF-32 时需要添加四个额外字节,因为这些编码会在文本开头添加 BOM U+FEFF。(如果您不想这样,请使用无 BOM 编码之一,例如UTF-16BE或UTF-16LE。)
我的意思是,字素是否可能需要说 3 个 UTF-16 代码点,但在转换时需要 10 个 UTF-8 代码点?
不,这意味着某种其他类型的转换,如分解。输入的标量值的数量等于输出的标量值的数量,可能在开头添加了 U+FEFF 字节顺序标记。(我说“标量值”而不是“代码点”,因为“标量值”不包括代理。如果您正在对可能有错误或可能是垃圾数据的文本进行转码,它不会改变结果的大小。)