2015-03-26 2 views
1

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

+0

Было бы политической проблемой объявить UTF-8 BOM запретом и просто не испустить его? –

+0

@KerrekSB: Возможно. Я ненавижу спецификации еще больше, чем следующий парень, но этот текстовый файл используется как минимум в 5 продуктах - некоторые из них написаны на C++, некоторые в Delphi, другие - приложения для Android и iOS. Я не хочу возиться с ним и рискнуть что-то сломать. –

ответ

3

Вы можете использовать QTextCodec::codecForUtfText, чтобы определить, есть ли массив спецификация:

QFile *file = ...; 
bool hasByteOrderMark = QTextCodec::codecForUtfText(file->peek(4), nullptr) != nullptr; 
// QTextCodec is owned by Qt - don't free 

в качестве ярлыка, вы можете эксплуатировать (без документов) тот факт, что QTextStream выключит generateByteOrderMark, если он не может определить кодировку из потока:

QTextStream stream(file); 
stream.setAutoDetectUnicode(true); 
stream.setCodec(QTextCodec::codecForMib(106)); // default to UTF-8 
stream.setGenerateByteOrderMark(true); 

stream.readLine(); // detect codec and possibly switch off generateByteOrderMark 

int mib = stream.codec()->mibEnum(); // detected codec, or UTF-8 (default set above) 
bool hasByteOrderMark = stream.generateByteOrderMark(); 

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

+0

Аккуратный трюк, обнаруживающий кодек для первых 4 байтов! –

+0

@ VioletGiraffe: спецификация UTF-16 - 2 байта ('0xFF 0xFE' для LE,' 0xFE 0xFF' для BE), спецификация UTF-8 - 3 байта ('0xEF 0xBB 0xBF') и спецификация UTF-32 составляет 4 байта ('0xFF 0xFE 0x00 0x00' для LE,' 0x00 0x00 0xFE 0xFF' для BE). Таким образом, вам нужно как минимум 4 байта, чтобы различать UTF-16LE и UTF-32LE (при условии, что у вас нет кодированного файла UTF-16LE с нулевым терминатором сразу после его спецификации). –

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