У меня есть текст: «Csuklási roham gyötörheti a svédeket, annyit emlegetik mostanság ismét a svéd modellt Magyarországon».

В исходном тексте вообще нет разрывов строк.

Когда я отправляю этот текст по электронной почте (с помощью Gmail), я получаю его в следующей кодировке:

Content-Type: text/plain; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable

Csukl=E1si roham gy=F6t=F6rheti a sv=E9deket, annyit emlegetik mostans=E1g =
ism=E9t a
sv=E9d modellt Magyarorsz=E1gon. 

В HTML:

Content-Type: text/html; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable


<span class=3D"Apple-style-span" style=3D"font-family: Helvetica, Verdana, = sans-serif; font-size: 15px; ">Csukl=E1si roham gy=F6t=F6rheti a sv=E9deket= , annyit emlegetik mostans=E1g ism=E9t a sv=E9d modellt Magyarorsz=E1gon.

....

Когда я пытаюсь разобрать тело письма как text / plain, я не могу избавиться от знака = "mostans = E1g = ism = E9t" между двумя словами. Обратите внимание, что этот же символ отсутствует в сообщении, закодированном в HTML. Я понятия не имею, что это за специальный символ, но мне нужно удалить его, чтобы вернуть исходный текст.

Я попытался заменить '\ n', но это не тот случай, если я нажму «Enter» в тексте, я могу правильно заменить его на любой символ, который я хочу. Я также пробовал '\ r' и '\ t'.

Итак, вопрос в том, что мне не хватает? Откуда этот особый персонаж? Это из-за charser и / или кодировки передачи? Если да, то что мне нужно сделать, чтобы решить проблему и вернуть исходный текст.

Любая помощь приветствуется.

Ура, Балаж

5
Balázs Németh 11 Ноя 2010 в 14:42

2 ответа

Лучший ответ

Вам необходимо использовать MimeUtility. Вот пример.

public class Mime {
    public static void main(String[] args) throws MessagingException,
            IOException {
        InputStream stringStream = new FileInputStream("mime");
        InputStream output = MimeUtility.decode(stringStream,
                "quoted-printable");
        System.out.println(convertStreamToString(output));
    }

    public static String convertStreamToString(InputStream is)
            throws IOException {
        /*
         * To convert the InputStream to String we use the Reader.read(char[]
         * buffer) method. We iterate until the Reader return -1 which means
         * there's no more data to read. We use the StringWriter class to
         * produce the string.
         */
        if (is != null) {
            Writer writer = new StringWriter();

            char[] buffer = new char[1024];
            try {
                Reader reader = new BufferedReader(new InputStreamReader(is,
                        "ISO8859_1"));
                int n;
                while ((n = reader.read(buffer)) != -1) {
                    writer.write(buffer, 0, n);
                }
            } finally {
                is.close();
            }
            return writer.toString();
        } else {
            return "";
        }
    }
}

Файл 'mime' содержит закодированный текст:

Csukl=E1si roham gy=F6t=F6rheti a sv=E9deket, annyit emlegetik mostans=E1g =
ism=E9t a
sv=E9d modellt Magyarorsz=E1gon.

ОБНОВЛЕНИЕ:

Использование библиотеки Guava:

    InputSupplier<InputStream> supplier = new InputSupplier<InputStream>() {
        @Override
        public InputStream getInput() throws IOException {
            InputStream inStream = new FileInputStream("mime");
            InputStream decodedStream=null;
            try {
                decodedStream = MimeUtility.decode(inStream,
                "quoted-printable");
            } catch (MessagingException e) {
                e.printStackTrace();
            }
            return decodedStream;
        }
    };
    InputSupplier<InputStreamReader> result = CharStreams
    .newReaderSupplier(supplier, Charsets.ISO_8859_1);
    String ans = CharStreams.toString(result);
    System.out.println(ans);
3
Emil 17 Ноя 2010 в 08:59
Мария Немет: да, он удален, но я вижу лишнюю новую строку, которой не было в исходном тексте. Может быть, это похоже на то, что говорит jarnbjo, что «цитируемая печать» запрещает закодированным строкам превышать длину 76 символов.
 – 
Emil
11 Ноя 2010 в 17:09
Мария Немет: Прочтите о Quoted-printable. Это поможет вам разобраться в кодировке .
 – 
Emil
11 Ноя 2010 в 17:12
Оно работает. convertStreamToString немного сбивает с толку, поскольку InputStream output = MimeUtility.decode (stringStream, "quoted-printable"); был ключевым, но подавляющее большинство вашего ответа было тем методом, упомянутым выше :)
 – 
Balázs Németh
11 Ноя 2010 в 17:15
Мария Немет: Вы также получаете дополнительную новую строку?
 – 
Emil
11 Ноя 2010 в 17:27
Я был неправ, я вижу эти лишние строки, да! Значит, у меня есть \ n и \ r \ n, причем последний настоящий?
 – 
Balázs Németh
11 Ноя 2010 в 17:37

Кодировка передачи "цитируемый-печатный" запрещает кодируемым строкам превышать длину 76 символов. Если кодируемый текст содержит более длинные текстовые строки, необходимо вставить «мягкий разрыв строки», который обозначается одиночным знаком «=» в качестве последнего символа закодированной строки. Это означает, что следующий разрыв строки вставляется только для выполнения ограничения в 76 символов и что следующий разрыв строки должен быть удален при декодировании кодировки передачи.

2
jarnbjo 11 Ноя 2010 в 15:30
Вдобавок к этому разрыв строки, скорее всего, будет «\ r \ n», а не просто «\ r» или «\ n».
 – 
Christoffer Hammarström
11 Ноя 2010 в 15:43
1
Это не только вероятно, но и обязательно. В кавычках для печати разрешены только разрывы строк CRLF (\ r \ n).
 – 
jarnbjo
11 Ноя 2010 в 15:48