Некоторая информация:
Что происходит, когда я запускаю это
Я получаю ожидаемую строку «abcd», пока она не достигнет позиции 4094 символа. После этого выводится только этот знак «?» до конца файла.
Что я думаю об этом?
Я думаю, что это не ожидаемое поведение, и это должно быть где-то ошибка.
Код, который вы можете проверить с помощью:
#include <iostream>
#include <fstream>
#include <locale>
#include <codecvt>
void createTestFile() {
std::ofstream file ("utf16le.txt", std::ofstream::binary);
if (file.is_open()) {
uint16_t bom = 0xFEFF; // UTF-16 little endian BOM
uint64_t abcd = 0x0064006300620061; // UTF-16 "abcd" string
file.write((char*)&bom,2);
for (size_t i=0; i<2000; i++) {
file.write((char*)&abcd,8);
}
file.close();
}
}
int main() {
//createTestFile(); // uncomment to make the test file
std::wifstream file;
std::wstring line;
file.open("utf16le.txt");
file.imbue(std::locale(file.getloc(), new std::codecvt_utf16<wchar_t, 0x10ffff, std::consume_header>));
if (file.is_open()) {
while (getline(file,line)) {
std::wcout << line << std::endl;
}
}
}
Это похоже на библиотечную ошибку для меня. Пошаговое выполнение программы-примера, скомпилированной gcc 7.1.1 с использованием gdb
:
(gdb) n
28 while (getline(file,line)) {
(gdb) n
29 std::wcout << line << std::endl;
(gdb) p line.size()
$1 = 8000
8000 символов прочитано, как и ожидалось. Но потом:
(gdb) p line[4092]
$18 = (__gnu_cxx::__alloc_traits<std::allocator<wchar_t> >::value_type &) @0x628240: 97 L'a'
(gdb) p line[4093]
$19 = (__gnu_cxx::__alloc_traits<std::allocator<wchar_t> >::value_type &) @0x628244: 98 L'b'
(gdb) p line[4094]
$20 = (__gnu_cxx::__alloc_traits<std::allocator<wchar_t> >::value_type &) @0x628248: 25344 L'挀'
(gdb) p line[4095]
$21 = (__gnu_cxx::__alloc_traits<std::allocator<wchar_t> >::value_type &) @0x62824c: 25600 L'搀'
(gdb) p line[4096]
$22 = (__gnu_cxx::__alloc_traits<std::allocator<wchar_t> >::value_type &) @0x628250: 24832 L'愀'
line[4092]
а также line[4093]
смотри хорошо Но потом я вижу line[4094]
, line[4095]
, а также line[4096]
, содержащий 6300
, 6400
а также 6500
, вместо 0063
, 0064
, а также 0065
,
Таким образом, это запутано, начиная с символа 4094, а не 4096, на самом деле. Я сбросил бинарный файл UTF-16, и он мне кажется правильным. За маркером спецификации следует постоянный порядок байтов для всего содержимого файла.
Единственное, что озадачивает, — это то, почему предположительно затронуты и clang, и gcc, но быстрый поиск в Google показывает, что clang также использует libstdc ++ от gcc, по крайней мере, до недавнего времени. Итак, для меня это выглядит как ошибка libstdc ++.
Других решений пока нет …