2008-09-22 3 views
51

Я обрабатываю некоторые файлы данных, которые должны быть действительными UTF-8, но не являются, что приводит к сбою анализатора (не под моим контролем). Я хотел бы добавить этап предварительной проверки данных для корректности UTF-8, но я еще не нашел полезности, чтобы помочь в этом.Как проверить, действительно ли файл UTF-8?

Там в web service в W3C, который, как представляется, быть мертвым, и я нашел Windows-только проверку tool, подотчетная недопустимые UTF-8 файлов, но не сообщает, какие строки/символы исправить.

Я был бы доволен либо инструментом, который я могу зайти и использовать (в идеале кросс-платформенным), либо скриптом ruby ​​/ perl, который я могу сделать частью процесса загрузки данных.

ответ

72

Вы можете использовать GNU Iconv:

$ iconv -f UTF-8 your_file -o /dev/null 

Или с более старыми версиями Iconv, например, на MacOS:

$ iconv -f UTF-8 your_file > /dev/null; echo $? 

Команда возвращает 0, если файл может быть преобразован успешно, и 1 если нет. Кроме того, он будет распечатывать смещение байта, где произошла некорректная последовательность байтов.

Редактировать: Кодировка вывода не обязательно должна быть указана, она будет считаться UTF-8.

+13

В старых версиях iconv, как на OSX или в fink, флаг -o отсутствует. Однако перенаправление stdout всегда должно работать. – 2008-09-22 15:07:59

+1

Torsten, спасибо, что отлично работает на моей Linux-машине. Я не мог найти версию утилиты iconv для cygwin, но это не демонстрация. – 2008-09-22 16:16:48

+2

не поймать все проблемы ... – zvolkov 2011-10-04 00:28:26

10

Использование функций python и str.encode | декодирования.

>>> a="γεια" 
>>> a 
'\xce\xb3\xce\xb5\xce\xb9\xce\xb1' 
>>> b='\xce\xb3\xce\xb5\xce\xb9\xff\xb1' # note second-to-last char changed 
>>> print b.decode("utf_8") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/local/lib/python2.5/encodings/utf_8.py", line 16, in decode 
    return codecs.utf_8_decode(input, errors, True) 
UnicodeDecodeError: 'utf8' codec can't decode byte 0xff in position 6: unexpected code byte 

Исключено заброшенное запрошенное значение в свойстве .args.

>>> try: print b.decode("utf_8") 
... except UnicodeDecodeError, exc: pass 
... 
>>> exc 
UnicodeDecodeError('utf8', '\xce\xb3\xce\xb5\xce\xb9\xff\xb1', 6, 7, 'unexpected code byte') 
>>> exc.args 
('utf8', '\xce\xb3\xce\xb5\xce\xb9\xff\xb1', 6, 7, 'unexpected code byte') 
3

Как насчет библиотеки gnu iconv? Использование функции iconv(): «На входе встречается недопустимая многобайтовая последовательность. В этом случае она устанавливает errno в EILSEQ и возвращает (size_t) (- 1). * Inbuf остается указателем на начало недопустимой многобайтовой последовательности. "

EDIT: oh - i пропустил ту часть, где вы хотите использовать язык сценариев. Но для работы в командной строке утилита iconv также должна быть проверена.

-3

Код на C++, приведенный ниже, основан на одном, опубликованном на многих сайтах через Интернет. Я исправил ошибку в исходном коде и добавил возможность получить как позицию недопустимого символа, так и недействительный символ.

///Returns -1 if string is valid. Invalid character is put to ch. 
int getInvalidUtf8SymbolPosition(const unsigned char *input, unsigned char &ch) { 
    int     nb, na; 
    const unsigned char *c = input; 

    for (c = input; *c; c += (nb + 1)) { 
    if (!(*c & 0x80)) 
     nb = 0; 
    else if ((*c & 0xc0) == 0x80) 
    { 
     ch = *c; 
     return (int)c - (int)input; 
    } 
    else if ((*c & 0xe0) == 0xc0) 
     nb = 1; 
    else if ((*c & 0xf0) == 0xe0) 
     nb = 2; 
    else if ((*c & 0xf8) == 0xf0) 
     nb = 3; 
    else if ((*c & 0xfc) == 0xf8) 
     nb = 4; 
    else if ((*c & 0xfe) == 0xfc) 
     nb = 5; 
    na = nb; 
    while (na-- > 0) 
     if ((*(c + nb) & 0xc0) != 0x80) 
     { 
      ch = *(c + nb); 
      return (int)(c + nb) - (int)input; 
     } 
    } 

    return -1; 
} 
4

Вы можете использовать isutf8 из moreutils коллекции.

$ apt-get install moreutils 
$ isutf8 your_file 

В сценарии оболочки, используйте переключатель --quiet и проверить состояние выхода, который равен нулю для файлов, которые являются действительными UTF-8.

Смежные вопросы