2009-08-28 4 views
0

У меня есть наблюдатель файлов, который захватывает контент из растущего файла, закодированного с помощью utf-16LE. Первый бит данных, записанных на него, имеет доступную спецификацию - я использовал это, чтобы идентифицировать кодировку UTF-8 (какая МОСТ из моих файлов поступает в кодировку). Я ломаю спецификацию и перекодирую в UTF-8, поэтому мой парсер не волнуется. Проблема в том, что, поскольку это растущий файл, у каждого бита данных есть спецификация.Как определить различные кодировки без использования спецификации?

Вот мой вопрос - без добавления префикса BOM байт для каждого набора данных у меня есть (, потому что у меня нет контроля над источником) могу я могу просто посмотреть на нулевые байты, которые присущи UTF-16 \ 000, а затем использовать это как мой идентификатор вместо спецификации? Это вызовет у меня головные боли по дороге?

В моей архитектуре используется рубиновое веб-приложение, регистрирующее полученные данные во временном файле, когда мой парсер, написанный в java, забирает его.

Написать теперь мой идентификационный код/​​перекодирования выглядит следующим образом:

// guess encoding if utf-16 then 
    // convert to UTF-8 first 
    try { 
    FileInputStream fis = new FileInputStream(args[args.length-1]); 
    byte[] contents = new byte[fis.available()]; 
    fis.read(contents, 0, contents.length); 

    if ((contents[0] == (byte)0xFF) && (contents[1] == (byte)0xFE)) { 
     String asString = new String(contents, "UTF-16"); 
     byte[] newBytes = asString.getBytes("UTF8"); 
     FileOutputStream fos = new FileOutputStream(args[args.length-1]); 
     fos.write(newBytes); 
     fos.close(); 
    } 

    fis.close(); 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } 

UPDATE

Я хочу поддержать такие вещи, как евро, эм-тир, и другие символы как таковые. Я изменил код выше, чтобы посмотреть, как это и это, кажется, передать все мои тесты для этих персонажей:

// guess encoding if utf-16 then 
    // convert to UTF-8 first 
    try { 
    FileInputStream fis = new FileInputStream(args[args.length-1]); 
    byte[] contents = new byte[fis.available()]; 
    fis.read(contents, 0, contents.length); 
    byte[] real = null; 

    int found = 0; 

    // if found a BOM then skip out of here... we just need to convert it 
    if ((contents[0] == (byte)0xFF) && (contents[1] == (byte)0xFE)) { 
     found = 3; 
     real = contents; 

    // no BOM detected but still could be UTF-16 
    } else { 

     for(int cnt=0; cnt<10; cnt++) { 
     if(contents[cnt] == (byte)0x00) { found++; }; 

     real = new byte[contents.length+2]; 
     real[0] = (byte)0xFF; 
     real[1] = (byte)0xFE; 

     // tack on BOM and copy over new array 
     for(int ib=2; ib < real.length; ib++) { 
      real[ib] = contents[ib-2]; 
     } 
     } 

    } 

    if(found >= 2) { 
     String asString = new String(real, "UTF-16"); 
     byte[] newBytes = asString.getBytes("UTF8"); 
     FileOutputStream fos = new FileOutputStream(args[args.length-1]); 
     fos.write(newBytes); 
     fos.close(); 
    } 

    fis.close(); 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } 

Что вы думаете?

+0

Я не понимаю проблему (в первом абзаце вы ссылаетесь). Конечно, не каждый фрагмент будет иметь спецификацию, но, конечно же, начало файла. Поэтому для каждого файла помните, видели ли вы спецификацию, и если да, обработайте ее как UTF-16. –

+0

У вас нет смешанных кодировок в одном файле? –

+0

У меня нет контроля над файлом, который растет - вот почему я не могу просто перемотать файл. У меня нет смешанных кодировок в одном файле, но у меня есть смешанные кодировки, проходящие через сеть, в парсер, который принимает смешанные кодировки. – eyberg

ответ

6

В общем случае вы не можете идентифицировать кодировку символов потока данных со 100% точностью. Лучшее, что вы можете сделать, это попытаться декодировать с использованием ограниченного набора ожидаемых кодировок, а затем применить некоторые эвристики к декодированному результату, чтобы увидеть, выглядит ли он «похожим» на ожидаемом языке. (Но любая эвристика даст ложные срабатывания и ложные негативы для определенных потоков данных.) Альтернативно, поставьте человека в цикле, чтобы решить, какое декодирование имеет наибольший смысл.

Лучшим решением является переработка вашего протокола, чтобы все, что подавало данные, также предоставляло схему кодирования, используемую для данных. (И если вы не можете, обвините любого, кто отвечает за проектирование/внедрение системы, которая не может дать вам схему кодирования!).

EDIT: из ваших комментариев по вопросу файлы данных доставляются через HTTP. В этом случае вам следует организовать, чтобы ваш HTTP-сервер зачищал заголовок «content-type» запросов POST, доставляя данные, извлекал набор символов/кодировку из заголовка и сохранял его в пути/месте, которое может содержать ваш парсер файлов иметь дело с.

0

Это вызовет у вас головную боль по дороге, без сомнения. Вы можете проверить переменные нулевые байты для упрощенных случаев (только ASCII, UTF-16, либо порядок байтов), но как только вы начнете получать поток символов выше кодовой точки 0x7f, этот метод становится бесполезным.

Если у вас есть дескриптор файла, лучшим вариантом является сохранение текущего указателя файла, поиск в начале, чтение спецификации и поиск в исходное положение.

Либо это, либо помните спецификацию как-то.

Опираясь на содержание данных, это идея bad, если вы не уверены, что диапазон символов будет ограничен для всех входов.

+0

Опираясь на спецификацию - это худшая идея, если вы не уверены, что файл будет иметь ее. – dan04

+0

«Первый бит данных, записанных на него, имеет доступную спецификацию», был в вопросе, поэтому я абсолютно уверен :-) – paxdiablo

0

This question содержит несколько вариантов распознавания символов, которые, как представляется, не требуют спецификации.

В настоящее время мой проект использует jCharDet, но мне, возможно, придется посмотреть на некоторые другие параметры, перечисленные здесь, поскольку jCharDet не на 100% надежна.

+2

@jwaddell: Никакая схема обнаружения символов не будет на 100% надежной. –

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