Java Base64中的日语字符编码
我被要求修复我们电子邮件处理软件中的一个错误。 当主题编码如下的消息:Java Base64中的日语字符编码,java,encoding,base64,mime,Java,Encoding,Base64,Mime,我被要求修复我们电子邮件处理软件中的一个错误。 当主题编码如下的消息: =?ISO-2022-JP?B?GyRCR1s/LiVGJTklSC1qRnxLXDhsGyhC?= 接收时,它被错误解码-其中一个日文字符未正确呈现。它的渲染方式如下:配信テスト?日本語 应该是什么时候配信テスト㈱日本語 我不懂日语——很明显,其中一个字符,括号中的那个字符,没有被翻译出来 解码由javax.mail.internet.MimeUtility.decodeText执行 如果我用在线解码器试一下,我唯一发现
=?ISO-2022-JP?B?GyRCR1s/LiVGJTklSC1qRnxLXDhsGyhC?=
接收时,它被错误解码-其中一个日文字符未正确呈现。它的渲染方式如下:配信テスト?日本語 应该是什么时候配信テスト㈱日本語
我不懂日语——很明显,其中一个字符,括号中的那个字符,没有被翻译出来
解码由javax.mail.internet.MimeUtility.decodeText执行
如果我用在线解码器试一下,我唯一发现的是它似乎工作正常,所以我怀疑MimeUtility中有一个bug
所以我尝试了一些实验,以这个小程序的形式:
public class Encoding {
private static final Charset CHARSET = Charset.forName("ISO-2022-JP");
public static void main(String[] args) throws UnsupportedEncodingException {
String control = "繋がって";
String subject= "配信テスト㈱日本語";
String controlBase64 = japaneseToBase64(control);
System.out.println(controlBase64);
System.out.println(base64ToJapanese(controlBase64));
String subjectBase64 = japaneseToBase64(subject);
System.out.println(subjectBase64);
System.out.println(base64ToJapanese(subjectBase64));
}
private static String japaneseToBase64(String in) {
return Base64.encodeBase64String(in.getBytes(CHARSET));
}
private static String base64ToJapanese(String in) {
return new String(Base64.decodeBase64(in), CHARSET);
}
}
Base64和Hex类位于org.apache.commons.codec中
当我运行它时,输出如下:
GyRCN1IkLCRDJEYbKEI=
繋がって
GyRCR1s/LiVGJTklSCEpRnxLXDhsGyhC
配信テスト?日本語
第一个较短的日文字符串是一个控件,它返回与输入相同的内容,已使用字符集ISO-2022-JP转换为Base64并再次转换回。好的
第二个日文字符串是带有不可靠字符的字符串。正如你所看到的,它返回一个?而不是角色。Base64编码输出也不同于原始主题编码
抱歉,如果这太长了,我想彻底检查一下。发生了什么,如何正确解码此字符?尝试在编码中使用MS932或Shift JIS。意味着
private static final Charset CHARSET = Charset.forName("MS932");
日语中有不同的脚本,如汉字、片假名。有些编码(如Cp132)不支持某些日语字符。您面临的问题是您在代码中使用的编码ISO-2022-JP。请尝试在编码中使用MS932或Shift JIS。意味着
private static final Charset CHARSET = Charset.forName("MS932");
日语中有不同的脚本,如汉字、片假名。有些编码(如Cp132)不支持某些日语字符。您面临的问题是您在代码中使用的ISO-2022-JP编码。ISO-2022-JP使用称为ku和ten的字节对,索引到94×94的字符表中。失败的一对有ku 12和ten 73,这在我所基于的有效字符表中没有列出。所有ku=12似乎都未使用
维基百科也没有列出JIS X 0208的任何更新。可能发送方正在使用某种供应商定义的扩展?ISO-2022-JP使用称为ku和ten的字节对,索引到94×94的字符表中。失败的一对有ku 12和ten 73,这在我所基于的有效字符表中没有列出。所有ku=12似乎都未使用 维基百科也没有列出JIS X 0208的任何更新。也许发送方正在使用某种供应商定义的扩展?尽管ISO-2022-JP是一种可变宽度编码,Java似乎不支持它所在的字符集部分,这可能是因为ISO-2022-JP-2中缺少转义序列,而ISO-2022-JP-3和ISO-2022-JP-2004中不支持转义序列。但是,UTF-8、UTF-16和UTF-32不支持所有字符 UTF-32:
AAB+SwAAMEwAADBjAAAwZg==
繋がって
AACRTQAAT+EAADDGAAAwuQAAMMgAADIxAABl5QAAZywAAIqe
配信テスト㈱日本語
另外,不管是否使用UTF-32,当字符串按原样打印时,它们保留其自然编码并正常显示。尽管ISO-2022-JP是可变宽度编码,Java似乎不支持它所在的字符集部分,这可能是因为ISO-2022-JP-2中缺少转义序列,而ISO-2022-JP-3和ISO-2022-JP-2004中不支持转义序列。但是,UTF-8、UTF-16和UTF-32不支持所有字符
UTF-32:
AAB+SwAAMEwAADBjAAAwZg==
繋がって
AACRTQAAT+EAADDGAAAwuQAAMMgAADIxAABl5QAAZywAAIqe
配信テスト㈱日本語
另外,无论是否使用UTF-32,当字符串按原样打印时,它们保留其自然编码并正常显示。错误不在软件中,但主题字符串本身的编码不正确。其他软件可能能够通过对内容进行进一步假设来解码文本,就像通常假设0x80-0x9f范围内的字符是Cp1252编码的一样,尽管指定了ISO-8859-1或ISO-8859-15
ISO-2022-JP是一种多字符集编码,使用转义序列在实际使用的字符集之间切换。编码字符串以ESC$B开头,表示使用了字符集JIS X 0208-1983。有问题的字符编码为0x2d6a。该代码点未在引用的字符集中定义,但后来添加到JIS X 0213:2000(JIS X字符集规范的较新版本)中 错误不在您的软件中,但主题字符串本身的编码不正确。其他软件可能能够通过对内容进行进一步假设来解码文本,就像通常假设0x80-0x9f范围内的字符是Cp1252编码的一样,尽管指定了ISO-8859-1或ISO-8859-15 ISO-2022-JP是一种多字符集编码,使用转义序列进行转换
在实际使用的字符集之间进行切换。编码字符串以ESC$B开头,表示使用了字符集JIS X 0208-1983。有问题的字符编码为0x2d6a。该代码点未在引用的字符集中定义,但后来添加到JIS X 0213:2000(JIS X字符集规范的较新版本)中 尝试在编码中使用MS932。表示私有静态最终字符集Charset=Charset.forNameMS932;您是否尝试使用SHIFT-JIS作为字符集?好的,但通常您应该将UTF-8转换为Base64。。。使用MS932是可行的,使用SHIFT-JIS产生的结果与以前相同。Mime编码字符串指定ISO-2022-JP,我不太愿意忽略指定的编码。MS932是Windows代码页932,它实际上是带有微软扩展的JIS X 0208。就像你看到的latin1包含微软的智能引号一样。试着在编码中使用MS932。表示私有静态最终字符集Charset=Charset.forNameMS932;您是否尝试使用SHIFT-JIS作为字符集?好的,但通常您应该将UTF-8转换为Base64。。。使用MS932是可行的,使用SHIFT-JIS产生的结果与以前相同。Mime编码字符串指定ISO-2022-JP,我不太愿意忽略指定的编码。MS932是Windows代码页932,它实际上是带有微软扩展的JIS X 0208。就像你看到的latin1一样,它包含了微软的智能报价。