Я пытаюсь читать файлы CSV с помощью Java. Некоторые файлы могут иметь отметку порядка байтов в начале, но не все. Когда он присутствует, порядок байтов читается вместе с остальной частью первой строки, что вызывает проблемы со сравнением строк.
Есть ли простой способ пропустить отметку порядка байтов, когда она присутствует?
Ответы:
РЕДАКТИРОВАТЬ : я сделал правильный выпуск на GitHub: https://github.com/gpakosz/UnicodeBOMInputStream
Вот класс, который я написал некоторое время назад, я просто отредактировал имя пакета перед вставкой. Ничего особенного, это очень похоже на решения, опубликованные в базе данных ошибок SUN. Включите это в свой код, и все будет в порядке.
И вы используете это так:
источник
В библиотеке ввода-вывода Apache Commons есть инструмент,
InputStream
который может обнаруживать и удалять спецификации:BOMInputStream
(javadoc) :Если вам также необходимо обнаруживать разные кодировки, он также может различать различные метки порядка байтов, например, UTF-8 и UTF-16 big + little endian - подробности см. По ссылке на документ выше. Затем вы можете использовать обнаруженный
ByteOrderMark
чтобы выбратьCharset
для декодирования потока. (Вероятно, есть более упрощенный способ сделать это, если вам нужна вся эта функциональность - может быть, UnicodeReader в ответе BalusC?). Обратите внимание, что, как правило, нет очень хорошего способа определить, в какой кодировке находятся некоторые байты, но если поток начинается с спецификации, очевидно, это может быть полезно.редактировать : если вам нужно обнаружить спецификацию в UTF-16, UTF-32 и т.д., то конструктор должен быть:
Проголосуйте за комментарий @ martin-charlesworth :)
источник
boolean
аргумент, указывающий, следует ли включать или исключать спецификацию. Пример:BOMInputStream bomIn = new BOMInputStream(in, false); // don't include the BOM
BOMInputStream bomIn = new BOMInputStream(is, ByteOrderMark.UTF_8, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_32BE, ByteOrderMark.UTF_32LE);
BOMInputStream(InputStream delegate) Constructs a new BOM InputStream that excludes a ByteOrderMark.UTF_8 BOM.
Более простое решение:
Пример использования:
Он работает со всеми 5 кодировками UTF!
источник
В Google Data API есть приложение,
UnicodeReader
которое автоматически определяет кодировку.Вы можете использовать его вместо
InputStreamReader
. Вот немного сжатый отрывок из его источника, который довольно прост:источник
(bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)
чтобы быть правдой, тогда UTF-16LE case ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)
) уже соответствовал бы.В
Apache Commons IO
библиотеках BOMInputStream уже упомянута @rescdsk, но я не видел его уже , как получитьInputStream
без спецификации.Вот как я это сделал в Scala.
источник
public BOMInputStream(InputStream delegate) { this(delegate, false, ByteOrderMark.UTF_8); }
. ПоUTF-8 BOM
умолчанию исключает .Constructs a new BOM InputStream that excludes a ByteOrderMark.UTF_8 BOM.
Чтобы просто удалить символы спецификации из вашего файла, я рекомендую использовать Apache Common IO
Установите для include значение false, и ваши символы спецификации будут исключены.
источник
К сожалению, нет. Вам придется идентифицировать себя и пропустить. На этой странице подробно описано, на что вам следует обратить внимание. Также см. Этот вопрос SO для более подробной информации.
источник
У меня была та же проблема, и, поскольку я не читал кучу файлов, я нашел более простое решение. Я думаю, что моя кодировка была UTF-8, потому что, когда я распечатал оскорбительный символ с помощью этой страницы: Получить значение Unicode символа, я обнаружил, что это так
\ufeff
. Я использовал код,System.out.println( "\\u" + Integer.toHexString(str.charAt(0) | 0x10000).substring(1) );
чтобы распечатать оскорбительное значение Unicode.Как только у меня появилось оскорбительное значение Unicode, я заменил его в первой строке моего файла, прежде чем продолжить чтение. Бизнес-логика этого раздела:
Это устранило мою проблему. Затем я смог продолжить обработку файла без проблем. Я добавил,
trim()
что в случае начального или конечного пробела, вы можете сделать это или нет, в зависимости от ваших конкретных потребностей.источник