Java CharsetDecoder, вставляющий пробел после каждого символа

#java #utf-8 #groovy

#java #utf-8 #groovy

Вопрос:

Я пытаюсь использовать этот код (найденный в Stackoverflow) для удаления недопустимых символов UTF-8:

 def text = file.text
CharsetDecoder utf8Decoder = Charset.forName("UTF-8").newDecoder();
utf8Decoder.onMalformedInput(CodingErrorAction.IGNORE);
utf8Decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
ByteBuffer bytes = ByteBuffer.allocate(text.getBytes().length * 2)
CharBuffer cbuf = bytes.asCharBuffer()
cbuf.put(text)
cbuf.flip()
CharBuffer parsed = utf8Decoder.decode(bytes);
println parsed.toString()
  

Результат, который я получаю, выглядит следующим образом:

  < d o c u m e n t >
     < t i t l e > S o me  T i t l e   < / t i t l e >
     < s i t e > A S i t e < / s i t e >
  

Есть идеи о том, почему он так себя ведет?

Комментарии:

1. Есть ли какие-либо доступные для публикации входные данные, которые вы можете предоставить?

2. Разве вы не должны указывать кодировку в text.getBytes() ? Однако я сомневаюсь, что это причина проблемы. Кроме того, указываете ли вы какую-либо кодировку при открытии / чтении файла?

3. Я подозреваю, что file.text использует кодировку символов платформы по умолчанию, но, похоже, она не указана . Вероятно, вам следует использовать тот, который позволяет указать кодировку , или File.getBytes() , чтобы получить необработанные байты. В противном случае байты уже были преобразованы один раз, вполне возможно, с неправильной кодировкой.

Ответ №1:

Понятия не имею, почему это не сработало, но это то, что это исправило (код в Groovy, а не Java):

 file.withInputStream { stream ->
    CharsetDecoder utf8Decoder = Charset.forName("UTF-8").newDecoder();
    utf8Decoder.onMalformedInput(CodingErrorAction.IGNORE);
    utf8Decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
    def reader = new BufferedReader(new InputStreamReader(stream, utf8Decoder))
    def line = null

    def sb = new StringBuilder()
    while ( (line = reader.readLine()) != null) {
        sb.append("$linen")
    }
    reader.close()
}