При попытке прочитать файл в кодировке UTF-16 с подсказками из этого ответа у меня возникла проблема, заключающаяся в том, что после считывания нескольких тысяч символов метод getline
начинает читать в мусоджаке для мусора.
Вот мой главный:
#include <cstdio>
#include <fstream>
#include <iostream>
#include <codecvt>
#include <locale>
int main(void) {
std::wifstream wif("test.txt", std::ios::binary);
setlocale(LC_ALL, "en_US.utf8");
if (wif.is_open())
{
wif.imbue(
std::locale(
wif.getloc(),
new std::codecvt_utf16<wchar_t, 0x10ffff, std::consume_header>
)
);
std::wstring wline;
while (std::getline(wif, wline))
{
std::wcout << wline;
}
wif.close();
}
return 0;
}
Файл test.txt
содержит FF
, FE
метку порядка байтов, за которой следуют 100 строк с 80 'a'
с в каждой строке. Вот bash-скрипт, который генерирует test.txt
на * nix:
#!/bin/bash
echo -n -e \\xFF\\xFE > test.txt
for i in $(seq 1 100)
do
for i in $(seq 1 80)
do
echo -n -e \\x61\\x00 >> test.txt
done
echo -n -e \\x0A\\x00 >> test.txt
done
Вот как я компилирую и запускаю основной:
g++-8 -std=c++17 -g main.cpp -o m && ./m
То, что я ожидал: напечатано 8000 'a'
с.
Что на самом деле произошло:
После печати нескольких тысяч a
s вывод изменится на следующий мусор:
аааааааааа 愀 愀 愀 愀 愀 愀 愀 愀 愀 愀
и иногда непечатные символы, которые выглядят как 0A00
в прямоугольнике.
Символ 愀
имеет двоичное значение кодовой точки 110000100000000
, поэтому он выглядит как a
-байт, а затем 0
-байт.
Кажется, что некоторые байты теряются во время чтения, и с этого момента все смещается, а все остальные символы декодируются неправильно. Или, поскольку выходные данные заканчиваются символом 0A00
, может быть, что после считывания нескольких тысяч a
s порядок байтов меняется на обратный, но такое поведение также не имеет никакого смысла.
Почему это происходит, и как проще всего это исправить?