【问题标题】:Character-encoding not preserved when dealing with InputStreamReader even after using UTF8即使在使用 UTF8 后处理 InputStreamReader 时也不会保留字符编码
【发布时间】:2021-08-21 07:05:47
【问题描述】:

有数据:

batiment:Kube D
etage:4ème
description:some_description

我想通过 InputStreamReader 的东西来获取这些数据:

SharedByteArrayInputStream sbais = (SharedByteArrayInputStream) content;
Reader reader = new InputStreamReader(sbais, Charset.forName("UTF8"));
int size = sbais.available();
char[] theChars = new char[size];
int data = reader.read();
int i = 0;
while (data != -1) {
    theChars[i] = (char) data;
    i++;
    data = reader.read();  
}
String parse = new String(theChars);
String[] parties = parse.split("Content-Transfer-Encoding: quoted-printable");
String partie = (parties[1]).trim();
parties = partie.split("\\R");
String ret = "";
for(String ligne : parties) {
   if (ligne == null || ligne.trim().equals(""))
        break;
   ret = ret.concat(ligne).concat(System.lineSeparator());
}
return ret;

在运行时,数据4ème 被转换为4=E8me

那么有什么问题呢?

编辑:

这是内容的标题:

--_008_DB6P190MB0166B6F4DE5E31397B4A7B558C3C9DB6P190MB0166EURP_
Content-Type: multipart/alternative;
    boundary="_000_DB6P190MB0166B6F4DE5E31397B4A7B558C3C9DB6P190MB0166EURP_"

--_000_DB6P190MB0166B6F4DE5E31397B4A7B558C3C9DB6P190MB0166EURP_
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

batiment:KUBE D
etage:4=E8me
description:andrana

Cordialement,

...

【问题讨论】:

  • 我使用的是 java 8
  • 4=E8me4ème 的引用可打印编码。 IE。您的数据经过编码以便传输,您需要对其进行解码。
  • 我从javax.mail.Message 内容(getContent())获得输入
  • @JoachimSauer 如何解码?

标签: java character-encoding


【解决方案1】:

按照 Obourgain 的回答后,这里是工作代码:

SharedByteArrayInputStream sbais = (SharedByteArrayInputStream) content;
Reader reader = new InputStreamReader(sbais, StandardCharsets.ISO_8859_1);
int size = sbais.available();
char[] theChars = new char[size];
int data = reader.read();
int i = 0;
while (data != -1) {
    theChars[i] = (char) data;
    i++;
    data = reader.read();  
}
String parse = new String(theChars);
String[] parties = parse.split("Content-Transfer-Encoding: quoted-printable");
String partie = (parties[1]).trim();
String[] lignes = partie.split("\\R");
String ret = "";
for(String ligne : lignes) {
     if (ligne == null || ligne.trim().equals(""))
        break;
     String tmp = new QuotedPrintableCodec(StandardCharsets.ISO_8859_1).decode(ligne, StandardCharsets.ISO_8859_1);
     ret = ret.concat(tmp).concat(System.lineSeparator());
}
return ret;

【讨论】:

    【解决方案2】:

    我们可以看到你忽略了字符串Content-Transfer-Encoding: quoted-printable之前的所有内容。

    也就是说你的初始内容实际上是4=E8me,对应一个ISO-8859-1字符串,用quoted-printable编码。

    如果要将其转换为4ème,则必须对其进行解码。

    没有什么开箱即用的,但this 的回答会给你一些可以使用的库的想法。

    例如使用Apache Common Codec,它会是这样的:

        partie = new QuotedPrintableCodec(StandardCharsets.ISO_8859_1).decode(partie);
    

    【讨论】:

    • 我使用 Apache 通用编解码器,但出现异常 Invalid URL encoding: not a valid digit (radix 16): 34
    • 这取决于您输入字符串的内容。在内容中,您应该找到描述编码的标题。类似Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: quoted-printable
    • 当我找到标题时该怎么办?
    • 将它们添加到您的问题中。很难为您提供帮助,因为我们不知道您的 String 是如何编码的,或者即使它是正确编码的。为了得到一个好的答案,我们需要从您的样本中获取变量parse 的内容。
    • 好的,我编辑了帖子以在我要检索的数据之前包含标题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    相关资源
    最近更新 更多