Как определить спецификацию с использованием классов Qt? То, что я пытаюсь сделать, это прочитать файл UTF-8, манипулировать его содержимым и записать его обратно. Я могу выбрать либо установить, либо отбросить спецификацию с помощью QTextStream
, но я не вижу способа сохранить его исходный статус (наличие или отсутствие), потому что я не могу его запросить.Как определить, имеет ли текстовый файл спецификацию Unicode или нет?
ответ
Вы можете использовать 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();
Это недокументированная поведение, так что если вы хотите, чтобы полагаться на него, вы можете проверить.
Аккуратный трюк, обнаруживающий кодек для первых 4 байтов! –
@ 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 с нулевым терминатором сразу после его спецификации). –
Было бы политической проблемой объявить UTF-8 BOM запретом и просто не испустить его? –
@KerrekSB: Возможно. Я ненавижу спецификации еще больше, чем следующий парень, но этот текстовый файл используется как минимум в 5 продуктах - некоторые из них написаны на C++, некоторые в Delphi, другие - приложения для Android и iOS. Я не хочу возиться с ним и рискнуть что-то сломать. –