Почему std::wofstream не печатает все wstring в файл?
У меня есть std::wstring
чей размер составляет 139 580 199 символов.
Для отладки я распечатал его в файл с таким кодом:
std::wofstream f(L"C:\\some file.txt");
f << buffer;
f.close();
После этого заметил, что конец строки отсутствует. Размер создаваемого файла составляет 109 592 584 байта (а "размер на диске" - 109 596 672 байта).
Также проверил, если буфер содержит нулевые символы, сделал это:
size_t pos = buffer.find(L'\0');
Ожидаемый результат будет std::wstring::npos
но это 18446744073709551615
, но моя строка не имеет нулевого символа в конце, так что, вероятно, все в порядке.
Может кто-нибудь объяснить, почему у меня не все строки напечатаны в файл?
1 ответ
Многое зависит от локали, но обычно файлы на диске не будут использовать ту же форму кодирования (или даже ту же кодировку), что и wchar_t
; filebuf
что делает фактическое чтение и запись переводит кодировки в соответствии с его проникновенным языком. И между длиной строки в разных кодировках или в форме кодирования существует только смутное соотношение.
(И размер, который видит система, не соответствует количеству байтов, которые вы можете прочитать из файла.)
Чтобы увидеть, все ли было написано, проверьте статус f
после закрытия, то есть:
f.close();
if ( !f ) {
// Something went wrong...
}
Одна вещь, которая может пойти не так, это то, что внешняя кодировка не имеет представления для одного из символов. Если вы в "C"
локаль, это может произойти для любого символа вне базового набора символов выполнения.
Если выше нет ошибки, нет никаких оснований полагать, что не вся строка была написана. Что произойдет, если вы попытаетесь прочитать это в другой программе? Вы получаете одинаковое количество символов или нет?
В остальном нуль-символы - это символы, подобные любым другим в std::wstring
; в них нет ничего особенного, в том числе когда они выводятся в поток. И 18446744073709551615 очень похож на значение, которое я ожидал бы дляstd::wstring::npos
на 64-битной машине.
РЕДАКТИРОВАТЬ:
В продолжение комментария Мэтта Петерссона: на самом деле очень маловероятно, что в файле будет меньше байтов, чем в коде. std::wstring
, (std::wstring::size()
возвращает количество кодовых точек.) Я думал с точки зрения байтов, а не с точки зрения того, что std::wstring::size()
возвращается. Таким образом, наиболее вероятным объяснением является то, что в вашей строке есть несколько символов, которые не могут быть представлены в целевой кодировке (которая, вероятно, поддерживает только символы с кодовыми точками 32–126, плюс несколько управляющих символов по умолчанию).