Передача первого символа строки в другую строку и использование std :: stoi для получения целочисленного значения, чтобы проверить, использует ли оно UTF-8 или Unicode (UTF-16) - PullRequest
0 голосов
/ 29 ноября 2018

Интересно, кто-нибудь мог бы помочь в этом вопросе?

Как мы знаем, файлы .txt, закодированные в UTF-8 и Unicode (UTF-16), имеют скрытые символы.

Я пишуПрограмма, которая принимает выбранный файл .txt с другой кодировкой UTF-8 и Unicode (UTF-16).Мне нужно получить первый символ строки и сохранить его.Что мне нужно сделать с этой строкой, так это взять ее, поместить в отдельную строку и использовать std :: stoi для получения значения int скрытого символа.

    //OPEN THE FILE IN BINARY
  std::fstream mazeFile(mazeFileLoc, std::ios::in | std::ios::binary);

  if (mazeFile.is_open())
  {
      //STORE THE FIRST CHARACTER AS AN CHAR VALUE
    char test = mazeFile.get();
    std::cout << "First Character is : " << test << std::endl;

    //PUT THE CHAR VALUE IN A STRING
    std::string strTest;
    strTest.insert(strTest.begin(), test);
    std::cout << "String First Character is : " << strTest << std::endl;

    //USE STOI TO GET THE INT VALUE OF STRING
    int testIntVal = std::stoi(strTest);
    std::cout << "Int Value of first character is : " << testIntVal << std::endl;

    mazeFile.close();
  }

Проблема, с которой я сталкиваюсь, заключается вон отмечает ошибку во время выполнения, когда я использую стои.

Кто-нибудь знает, почему это может быть ошибка, а не ее преобразование?

Ссылка на Git: https://github.com/xSwalshx/ANN.git

1 Ответ

0 голосов
/ 30 ноября 2018

std::stoi требует обработки исключений следующим образом:

int testIntVal; 
try
{
    testIntVal = std::stoi(strTest);
    std::cout << "Int Value of first character is : " << testIntVal << std::endl;
}
catch(...)
{
    std::cout << "not a valid integer\n";
}

Это неправильный способ проверки кодировки файлов.

Вы должны проверить BOM (Byte Order Mark), если файл имеет BOM, вы можете быть уверены в формате.

Если файл не имеет спецификации, вам нужно угадать, в каком формате вы не можете быть уверены.Если средство просмотра текста отображает содержимое как «123», то оно сохраняется как

0x31 0x32 0x33 //in UTF8 (same for ASCII characters)
0x31 0x00 0x32 0x00 0x33 0x00 //in UTF16
0x00 0x31 0x00 0x32 0x00 0x33 //in UTF16 big-endian

Обратите внимание, что UTF16-LE имеет нули для четных байтов в символах ASCII, UTF16-LE имеет нули для нечетных байтов, иUTF8 не имеет нулей.Вы можете начать со слабого предположения, что файл содержит только символы ASCII.Затем сделайте предположение о кодировке.См. Пример ниже.

Чтобы упростить задачу, вы должны использовать UTF8 для хранения текста.В Windows просто конвертируйте UTF16 в UTF8 и сохраняйте его, затем читайте UTF8 и конвертируйте в UTF16.Это будет совместимо и с другими системами.

const int FORMAT_UTF8 = 0;
const int FORMAT_UTF16 = 1;
const int FORMAT_UTF16BE = 2;

int get_file_encoding(const char* filename)
{
    printf("filename: %s ", filename);
    unsigned char buf[100] = { 0 };
    std::ifstream fin(filename, std::ios::binary);
    fin.read((char*)buf, sizeof(buf));
    int size = fin.gcount();

    //check for BOM
    if(size >= 3 && memcmp(buf, "\xef\xbb\xbf", 3) == 0)
    {
        printf("UTF8\n");
        return FORMAT_UTF8;
    }

    if(size >= 2 && memcmp(buf, "\xff\xfe", 2) == 0)
    {
        printf("UTF16\n");
        return FORMAT_UTF16;
    }

    if(size >= 2 && memcmp(buf, "\xfe\xff", 2) == 0)
    {
        printf("UTF16 big endian\n");
        return FORMAT_UTF16BE;
    }

    //BOM not found, let's take a guess!
    for(int i = 0; i < size - 1; i += 2)
    {
        if(buf[i + 1] == 0)
        {
            printf("assume UTF16\n");
            return FORMAT_UTF16;
        }

        if(buf[i] == 0)
        {
            printf("assume UTF16 big endian\n");
            return FORMAT_UTF16BE;
        }
    }

    printf("Assume ASCII or UTF8\n");
    return FORMAT_UTF8;
}
...