Рейтинг:
8
Jochen Arndt
Я не думаю, что он преобразован в ASCII. Но вы вводите в файл только один байт (Нижний байт вашего широкого символа). Для записи всех символьных байтов используйте:
write_on.write(buf, sizeof(wchar_t));
[РЕДАКТИРОВАТЬ]
См. сомментс. Универсальным решением должно быть:
write_on.write((char*)buf, wcslen(buf) * sizeof(wchar_t));
В вашем примере строка " ซ " записывается в файл одним символом Юникода (тайский символ SO SO). Предполагая, что ваша платформа использует кодировку UTF-16LE для широких символов (например, Windows), кодовая точка Unicode равна 0x0E0B, а содержимое двоичного файла будет 0x0B, за которым последует 0x0E.
При последующем чтении таких файлов вы должны знать, какая кодировка используется. Или более общий: Вы должны знать, как интерпретировать содержимое файла с каждым файлом, который вы хотите прочитать.
Если вы интерпретируете файл как ASCII (или какой-то 8-битный текст), вы будете читать управляющие символы ASCII 0x0B и 0x0E (VT и так далее). Но если вы интерпретируете его как UTF16-LE, вы получите кодовую точку 0x0E0B.
[/РЕДАКТИРОВАТЬ]
Sergey Alexandrovich Kryukov
Это, безусловно, так, но, строго говоря, не в 100% случаях, так что это почти правильно. Поэтому я проголосовал за ответ почти с 5: -).
Единственная недостающая часть-это упоминание о том, что wchar_t зависит от реализации и правильного объяснения этой "широкой" потери. В общем случае wchar_t не всегда является 16-битным, и массив не всегда будет иметь 1 элемент. Ваше решение верно при некоторых предположениях: например, когда подразумеваемая кодировка UTF-16, а wchar_t-16 бит, поэтому 16 бит, необходимых для представления этого конкретного символа, могут быть помещены в одно слово wchar_t.
Дополнительные пояснения см. в решении 2.
—СА
Jochen Arndt
Спасибо, Сергей. Вы правы, я должен был объяснить это более подробно.
Я использовал оператор sizeof (), чтобы учесть, что размер зависит от платформы. Таким образом, мой ответ верен во всех случаях для одного символа (как используется в вопросе). Для нескольких персонажей это конечно так
write_on. write(buf, wcslen(buf) * sizeof(wchar_t));
Sergey Alexandrovich Kryukov
Правильно. Вам лучше добавить этот фактор wcslen (buf) в ваше решение.
—СА
Member 11593571
в первую очередь без типажей баф на (типа char*), он не компилируется, так что я должен был сделать это так: write_on.писать (к(char*)buf с, wcslen(баф) * оператор sizeof(тип wchar_t)); но до сих пор не внес изменения и по-прежнему получать VT и поэтому вместо того, чтобы мой заказной характер.
Jochen Arndt
У вас есть широкая строка, состоящая из одного широкого символа. Предполагая, что ваша платформа использует UTF-16LE (как Windows), кодовая точка Unicode вашего символа равна 0x0E0B (тайский символ SO SO).
Это записывается в файл (он будет записывать значение, ориентированное на байт: 0x0B, за которым следует 0x0E).
Если вы теперь хотите прочитать файл, вы должны знать, как интерпретировать содержимое файла (как и любой файл, который Вы читаете). Если вы интерпретируете содержимое файла как символы ASCII, то увидите управляющие символы SO и VT. Но если вы интерпретируете содержимое как UTF-16LE, то получите символ 0x0E0B.
Поэтому, когда вы хотите вернуть своего персонажа, вы должны написать код, который выполняет обратную операцию:
- Получить размер файла
- Выделить тип wchar_t буфер (размер / оператор sizeof(тип wchar_t)) широкие символы (обычно добавляют один за завершающий нуль)
- Считывание содержимого файла в буфер (двоичный режим)
- Ваш персонаж(ы) вернется в выделенный буфер
Member 11593571
o. k я только что изменил 1 на sizeof(wchar_t), теперь он вводит на один символ больше, чем содержат сами буферные данные, прежде чем я имею в виду write_on. write(buf, 1); он преобразовывал мой пользовательский символ в (VT), но так, как вы сказали, как sizeof (wchar_t), он добавляет (SO) просто так, и именно так я читаю данные.
Read_From.открыть(Read_File_Name, а iOS::бинарные | ОС iOS::в); Read_From.читать(баф, оператор sizeof(буфер buf)); я также попытался Read_From.читать(буфер buf, 1);
Jochen Arndt
Нет никакого обращения.
Wchar_t представляет собой один символ, но содержит 2 или 4 байта в зависимости от реализации (см. ответ Сергея). Поэтому я выбрал sizeof(wchar_t), потому что это будет зависеть от реализации размера wchar_t в байтах.
Функция write записывает некоторое количество байтов из указанного буфера. Параметр buffer имеет тип char*. Но это не значит, что он пишет печатные символы. Он записывает байты.
Видишь http://www.cplusplus.com/reference/ostream/ostream/write/:
"Эта функция просто копирует блок данных, не проверяя его содержимое: Массив может содержать нулевые символы, которые также копируются без остановки процесса копирования."
Рейтинг:
2
Sergey Alexandrovich Kryukov
В дополнение к решению 1:
Пожалуйста, смотрите мой комментарий к этому вопросу.
Вы должны это понять wchar_t
является зависеть от реализации В Windows, в частности, он ориентирован на представление символов с использованием UTF-16L, одной из кодировок Unicode. Формально говоря, это не обязательно должна быть какая-то конкретная кодировка; это могут быть просто какие-то произвольные данные заданного размера этого типа. Все зависит от того, как эти данные интерпретируются.
Это означает, что один символ с кодовой точкой в BMP представлен в виде двух байтов, а другие символы используют пару 16-битных слов, называемых суррогатной парой. Итак, символ имел 2 или 4-байтовое представление; ваш случай, если 2 байта, так что вам не нужен массив wchar_t
, но в общем случае он вам понадобится. Затем вам нужно будет записать все элементы этого массива в свой файл и прочитать их соответствующим образом.
Смотреть также:
Широкий характер-Википедия, свободная энциклопедия,
BMP (Unicode) - Википедия, свободная энциклопедия,
"Дорожная карта" для БМП,
https://www.gnu.org/software/libunistring/manual/html_node/The-wchar_005ft-mess.html,
Часто задаваемые вопросы-UTF-8, UTF-16, UTF-32 & BOM[^].
—СА
Member 11593571
я прочитал все ссылки, которые вы дали мне выше, это было полезно, но не помогло мне решить мою проблему, так как вы сказали, что мой символ-это два байта, и wchar_t тоже может хранить два байта, тогда никаких проблем с тем, как я его ввожу, верно? и как я уже сказал выше, это, как я читал Read_From данных.открыть(Read_File_Name, а iOS::бинарные | ОС iOS::в); Read_From.читать(баф, оператор sizeof(тип wchar_t)); но не повезло там, я действительно не знаю, что я делаю не так, и что делать. но есть одна вещь, что если я использую один из символов ascii, он работает просто идеально.
Sergey Alexandrovich Kryukov
Как же так? Вы исправили свою ошибку с написанием 1?
—СА
Member 11593571
да, я изменил его на sizeof(wchar_t) или strlen(L"ซ"). я думаю, что это исправляет ошибку, но не устраняет мою проблему, так что у вас есть какие-нибудь идеи о том, как я могу написать ซ в своем текстовом файле?
Sergey Alexandrovich Kryukov
Или? Это две разные вещи. Извините, а какая именно строка после исправления? Какова ваша платформа?
—СА
Member 11593571
я использую windows
Sergey Alexandrovich Kryukov
Хорошо, тогда смотрите Решение 1. См. также комментарии к нему.
—СА
Member 11593571
я пробовал решения 1 и 2 снова и снова, но никаких изменений, и я прокомментировал Сергею Александровичу Крюкову ответ, если вы его прочтете.
Member 11593571
О боже, даже если я сделаю это просто cout < < "ซ"< & lt; endl; он печатает α ï ï. так что бы вы сказали сейчас?
Sergey Alexandrovich Kryukov
Вот в чем все дело: что значит"печатает"?
—СА
Andreas Gieriet
Во всей этой истории есть несколько составляющих:
1) ваш редактор: какую кодировку символов вы используете? Вы не можете доверять тому, что то, что вы видите, является тем, что получает компилятор. То есть попробуйте ввести символ в виде шестнадцатеричного кода L'\x..\x..' и т. д.
2) консоль, куда идет ваш printf: консоль получает последовательность байтов из вывода printf и должна иметь смысл в байтах. Убедитесь, что ваша консоль знает, как правильно отображать соответствующие последовательности байтов. например, моя консоль знает только 7-битный ASCII - другие символы отображаются как "мусор".
Овации
Энди
Sergey Alexandrovich Kryukov
Все дело в разделении интересов, исключении из уравнения всех несвязанных факторов. Каждый может сделать, например, круговую поездку, записать данные, прочитать их обратно и записать в другой файл, чтобы убедиться, что ничего не потеряно...
—СА
Sergey Alexandrovich Kryukov
Думаю, почти все знают. Я гарантирую, что если я что-то напишу, вы это прочтете.
Вы никогда не показывали свою дурацкую окончательную версию write с исправленной ошибкой и никогда не показывали, как Вы читаете.
—СА