【问题标题】:Groovy character encoding result mismatch for unsupported character不受支持的字符的 Groovy 字符编码结果不匹配
【发布时间】:2018-03-29 05:55:25
【问题描述】:

这是迄今为止我的分析和障碍,假设对于下面的字符,“UTF-8”字符集基本支持,“EUC-JP”不支持。 “——” 对于php,有一个方法“var_dump(input_string)”可以将任何字符串转换为编码为“EUC-JP”的字节数组,在这种情况下,它返回,

[161, 189, 10] //Note: [3]=>int(10) for Line Feed.

类似地,当我生成编码为“UTF-8”的字节数组时,在这种情况下它会返回,

[226, 128, 141,10] //Note: [4]=>int(10) for Line Feed.

但是,当我在 Groovy 中尝试同样的事情时, 它的行为完全不同,对于 EUC-JP 的字节排列如下,

[-95, -67, 10] //Note: [3]=>int(10) for Line Feed.

对于 UTF-8,

[-30, -128, -107, 10] //Note: [4]=>int(10) for Line Feed.

注意,我直接从 2 个分别用 EUC-JP 和 UTF-8 编码的不同文本文件中获取数据。上述所有数组的最后一个字节用于 LF(换行)。由于这两种语言的相同字符编码的字节排列不同,因此不可能匹配两者之间产生的哈希。

这是到目前为止的代码示例,从 php 开始,

<?php
$myfile = fopen("euc_jp.txt", "r") or die("Unable to open file!");
$str1 = fread($myfile,filesize("euc_jp.txt"));

echo "Read From File EUC-JP:<br/>";
echo $str1;
$byte_array1 = unpack('C*', $str1);
echo "<br/>Byte Dump of EUC-JP File Content:<br/>";
var_dump($byte_array1);

echo "<br/><br/>";
$myfile2 = fopen("utf_8.txt", "r") or die("Unable to open file!");
$str2 = fread($myfile2,filesize("utf_8.txt"));

echo "<br/><br/>";
echo "Read From File UTF-8:<br/>";
echo $str2;
$byte_array2 = unpack('C*', $str2);
echo "<br/>Byte Dump of EUC-JP File Content:<br/>";
var_dump($byte_array2);


$encodedToEucJp = mb_convert_encoding($str2, "EUC_JP");
echo "<br/><br/>After conversion (UTF-8) to (EUC-JP): <br/>";
echo $encodedToEucJp;

echo "<br/><br/>";

echo "Hash Generation Directly From EUC-JP:<br/>";
print_r(md5($str1));

echo "<br/><br/>";
echo "Hash Generation From UTF-8 File Content After Encoded to EUC-JP:<br/>";
print_r(md5($encodedToEucJp));

fclose($myfile);
fclose($myfile2);
?>

对于 Groovy,

println(new File('/var/www/html/euc_jp.txt').getText('EUC-JP').getBytes("EUC-JP"))
println(new File('/var/www/html/utf_8.txt').getText('UTF-8').getBytes("UTF-8"))

到目前为止,这是我的障碍,首先这两种语言的字节表示不同,如果不是 Groovy 和 Java8 的限制,我如何产生与 php 产生的相同的字节排列,其次,本机 php 函数 b_convert_encoding() 的等效代码是什么?所以,我能够转换任何字符串编码,其中可能有一些字符不支持两种编码机制。

【问题讨论】:

    标签: java php groovy utf-8 character-encoding


    【解决方案1】:

    Java 和 Groovy 字节是 two's complement 有符号 值,即一个字节的值介于 -128+127 之间。

    要计算同一字节对应的无符号值,请将256 添加到负值,例如-95 + 256 = 161

    所以,您看到的是相同的字节。只是 PHP 将值打印为 unsigned,而 Groovy 将值打印为 signed。它们在一个字节中仍然是相同的 8 位。

    Unsigned             Signed                 Hex
    161, 189, 10      == -95, -67, 10        == A1, BD, 0A
    226, 128, 141, 10 == -30, -128, -115, 10 == E2, 80, 8D, 0A
    226, 128, 149, 10 == -30, -128, -107, 10 == E2, 80, 95, 0A
    

    E2 80 8DUnicode Character 'ZERO WIDTH JOINER' (U+200D) 的 UTF-8。

    E2 80 95Unicode Character 'HORIZONTAL BAR' (U+2015) 的 UTF-8。

    如果您想将字节数组的值打印为可读文本,我建议您使用 2 位 HEX 打印字节。这样,每个字节的长度始终为 2 个十六进制数字。

    【讨论】:

    • 谢谢,您的回复对我帮助很大。我在这方面有另一个上下文,基本上我正在尝试编码一个包含字符“―”的字符串,使用 php 它平滑地编码为 EUC-JP 并以字节返回 [161, 189],但是,当我尝试要在 java 中编码相同的字符和相同的编码,它会简单地返回,“?”以字节为单位,它是 [63],我的期望是 [161, 189]。那么,我需要做些什么来解决这个问题。
    • @Md.HasanBasriAngel 那是因为EUC-JP中不存在“―”('HORIZONTAL BAR' (U+2015))。 “—” ('EM DASH' (U+2014)) 确实如此,作为字节 A1 BD
    • @Md.HasanBasriAngel 再次检查。 Unicode 字符 U+2015 不在该列表中,这就是您在上面的评论中发布的字符 (如果您不相信我,请复制/粘贴 here。 Unicode 字符 U+2014 is 在 EUC-JP 字符列表中,但这是一个 不同 字符,即使它们看起来非常相似。再次阅读我的previous comment!!
    • 再次感谢您,很抱歉之前的消息,请忽略。但我的问题是,在 php 中,他们通过这个转换函数 mb_convert_encoding($str2, "EUC_JP") 以某种方式管理它。我基本上是在 groovy 和 java 中寻找类似的机制。
    • @Md.HasanBasriAngel Java 遵循规范。 PHP 吐槽规范和does whatever it feels like。不要指望其他语言会这样做。如果您希望所有“看起来相似”的字符都映射到同一个 EUC_JP 字符,那么您需要找到“看起来相似”的定义,如果这样的定义存在的话。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多