Загрузка онлайн текста с разными кодировками

Я загружаю онлайн-текст, который могут загружать пользователи, поэтому тексты могут быть UTF-8, ISO-8859-1 и т. д.

Проблема в том, что я не знаю, какую кодировку используют пользователи, и если пользователь загрузил текст UTF-8, он работает отлично, но если пользователь загрузил текст ISO-8859-1 с акцентами (á é и т. .) эти символы отображаются неправильно.

Я пытался принудительно закодировать текст в UTF-8, но это не работает во всех случаях (buffer.toString("UTF-8"))

это мой код:

javaUrl = new URL(URLParser.parse(textResource.getUrlStr()));
                    connection = javaUrl.openConnection();                      
                    connection.setConnectTimeout(2000);
                    connection.setReadTimeout(2000);
                    InputStream input = new BufferedInputStream(connection.getInputStream());
                    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
                    int nRead;
                    try{        
                        byte [] data = new byte [1024];
                        while ((nRead = input.read(data, 0, data.length)) != -1) {
                            buffer.write(data, 0, nRead);
                        }
                        buffer.flush();
                        total = buffer.toString();                  
                    }finally{
                        input.close();
                        buffer.close();
                    }

person NullPointerException    schedule 13.07.2015    source источник
comment
У вас много проблем с обращением с ресурсами для начала...   -  person fge    schedule 13.07.2015


Ответы (1)


Поскольку у вас есть несколько возможных кодировок, и вы не знаете, какая из них правильная, у вас нет другого выбора, кроме как использовать здесь CharsetDecoder.

План:

  • открыть InputStream из соединения;
  • прочитать все содержимое в массив byte[];
  • попробуйте разные кодировки, пока не найдете подходящую.

Вот один из возможных способов найти правильную кодировку:

public boolean isCharset(final Charset charset, final byte[] contents)
    throws IOException
{
    final CharsetDecoder decoder = charset.newDecoder()
        .onMalformedInput(CodingErrorAction.REPORT);
    final ByteBuffer buf = ByteBuffer.wrap(contents);

    try {
        decoder.decode(buf);
        return true;
    } catch (CharacterCodingException ignored) {
        return false;
    }
}

Попробуйте это с другим набором кодировок (желательно, начиная с UTF-8).

person fge    schedule 13.07.2015
comment
мне нужно добиться этого без внешних сторонних библиотек, таких как Guava - person NullPointerException; 13.07.2015
comment
как можно использовать вашу функцию? дайте пример вызова параметра пожалуйста - person NullPointerException; 13.07.2015
comment
хорошо, я попробовал с isCharset(Charset.forName(ISO-8859-1), buffer.toByteArray()) и кажется, что это работает, теперь я должен проверить каждую возможную кодировку, пока не найду истину, а затем разобрать строку на эту кодировку ? - person NullPointerException; 13.07.2015
comment
Итак, вы имеете в виду, что вам действительно нужен строковый результат? И что потом делать с этим результатом? - person fge; 13.07.2015
comment
это работает, большое спасибо. Если это правда, я принудительно кодирую эту кодировку и работает нормально, спасибо - person NullPointerException; 13.07.2015
comment
Вместо того, чтобы угадывать кодировку, почему бы не использовать кодировку, о которой сообщает сервер? Если файл загружается через HTTP, введите connection в HttpURLConnection и вызвать его методы getHeaderFieldKey() и getHeaderField(), чтобы найти заголовок Content-Type и извлечь его атрибут charset. Сервер должен сообщить кодировку отправляемого текста. В случае файлов HTML, если в заголовке Content-Type нет charset, сам HTML может иметь тег <meta> для кодировки. - person Remy Lebeau; 15.07.2015
comment
@RemyLebeau, это правда, и это должна быть предпочтительная кодировка; однако в некоторых ситуациях у вас либо нет этого заголовка, либо этот заголовок врёт... - person fge; 15.07.2015