C ++ Как проверить файл Порядок порядка следования байтов, чтобы получить, если это UTF-8? - PullRequest
6 голосов
/ 02 февраля 2012

Интересно, как проверить метку порядка следования байтов в файле, чтобы узнать, является ли это UTF-8 в C ++?

Ответы [ 4 ]

10 голосов
/ 02 февраля 2012

Как правило, вы не можете.

Наличие метки порядка байтов является очень убедительным признаком того, что файл, который вы читаете, является Unicode.Если вы ожидаете текстовый файл, и первые четыре байта, которые вы получаете:

0x00, 0x00, 0xfe, 0xff -- The file is almost certainly UTF-32BE
0xff, 0xfe, 0x00, 0x00 -- The file is almost certainly UTF-32LE
0xfe, 0xff,  XX,   XX     -- The file is almost certainly UTF-16BE
0xff, 0xfe,  XX,   XX (but not 00, 00) -- The file is almost certainly UTF-16LE
0xef, 0xbb, 0xbf,  XX   -- The file is almost certainly UTF-8 With a BOM

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

Фактически, любой текстовый документ, содержащий только символы ASCIIот 0x00 до 0x7f является действительным документом UTF-8, а также простым документом ASCII.

Существуют эвристики, которые могут попытаться вывести, основываясь на видимых символах, кодируется ли документскажем, в ISO-8859-1, или UTF-8, или CP1252, но в целом первых двух, трех или четырех байтов файла недостаточно, чтобы определить, является ли то, что вы просматриваете, определенно UTF-8.

5 голосов
/ 02 февраля 2012

0xEF, 0xBB, 0xBF

порядок не зависит от порядкового номера.

Как вы читаете файл с C ++, зависит от вас.Лично я все еще использую методы в стиле C File, потому что они предоставляются библиотекой, с которой я кодирую, и я могу быть уверен, что укажу бинарный режим и буду избегать непреднамеренных переводов по линии.* cs.vt.edu

#include <fstream>
...
char buffer[100];
ifstream myFile ("data.bin", ios::in | ios::binary);
myFile.read (buffer, 3);
if (!myFile) {
    // An error occurred!
    // myFile.gcount() returns the number of bytes read.
    // calling myFile.clear() will reset the stream state
    // so it is usable again.
}
...
if (!myFile.read (buffer, 100)) {
    // Same effect as above
}
if (buffer[0] == 0XEF && buffer[1] == 0XBB && buffer[2] == 0XBF) {
    //Congrats, UTF-8
}

В качестве альтернативы, многие форматы используют UTF-8 по умолчанию, если не указаны другие спецификации (например, UTF-16 или UTF-32).

вики для спецификации

unicode.org.faq

4 голосов
/ 30 июля 2013
if (buffer[0] == '\xEF' && buffer[1] == '\xBB' && buffer[2] == '\xBF') {
    // UTF-8
}

Лучше использовать buffer[0] == '\xEF' вместо buffer[0] == 0xEF, чтобы избежать проблем со знаками / без знака, см. Как представить отрицательные значения символов в шестнадцатеричном формате?

1 голос
/ 28 мая 2018

Это моя версия на C ++:

#include <fstream>

/* Reads a leading BOM from file stream if it exists.
 * Returns true, iff the BOM has been there. */
bool ReadBOM(std::ifstream & is)
{
  /* Read the first byte. */
  char const c0 = is.get();
  if (c0 != '\xEF') {
    is.putback(c0);
    return false;
  }

  /* Read the second byte. */
  char const c1 = is.get();
  if (c1 != '\xBB') {
    is.putback(c1);
    is.putback(c0);
    return false;
  }

  /* Peek the third byte. */
  char const c2 = is.peek();
  if (c2 != '\xBF') {
    is.putback(c1);
    is.putback(c0);
    return false;
  }

  return true; // This file contains a BOM for UTF-8.
}
...