#c #c #stream #fstream
#c #c #поток #fstream
Вопрос:
У меня есть код C, который я пытаюсь преобразовать в C . Вкратце фрагмент кода на C выглядит следующим образом:
FILE *fp = fopen("temp.bin", "wb");
wchar_t* wide_word = _T("wide char");
char* word = "char";
fwprintf(fp, _T("%s"), wide_word);
fprintf(fp, "%s", word);
Преимущество в случае C заключается в том, что мы можем продолжать использовать один и тот же указатель fp для печати как char, так и wide char путем простой передачи указателя. Можем ли мы достичь того же в C без необходимости инициализации объектов ofstream
и wofstream
записи в тот же файл и получить точно такой же результат, что и в приведенной выше реализации C?
Я попробовал следующее на C (среди многих других вещей)
auto os = std::ofstream("temp_cpp.bin", std::ios::binary | std::ios::out);
wchar_t* wide_word = _T("wide char");
char* word = "char";
std::wstring st(wide_word);
std::string str(st.begin(),st.end());
os.write(reinterpret_cast<const char*>(str.c_str()), sizeof(str));
os.write(reinterpret_cast<const char*>(word), sizeof(word));
Комментарии:
1. Нет, по той же причине фрагмент кода требует, чтобы вы использовали оба
fprintf()
иfwprintf()
.2.
sizeof(str)
помните, чтоsizeof()
это константа времени компиляции вc
3. Обычно предполагается, что вы создаете файлы с одинаковой определенной кодировкой или поддерживаете правильную сериализацию данных. Вы могли бы использовать какой-нибудь хакерский трюк
reinterpret_cast
, но как вы собираетесь читать данные после этого?4. Данные используются в
wstring
переменной.5. Вы также не можете делать то, что вы представляете на C, и не иметь четко определенного результата. Потоки C являются либо байтово-ориентированными, либо широко ориентированными, в зависимости от характера первой функции ввода-вывода, которая будет использоваться на них, и вы не должны («не должны», согласно стандарту) применять широкие функции к байтово-ориентированным потокам или наоборот.
Ответ №1:
Да, вы можете использовать ту же write
функцию для записи байтов ANSI или байтов wide char в файл. В коде есть некоторые ошибки. sizeof(str)
вернет размер std::string
объекта, а не длину строки, и sizeof(word)
вернет размер указателя, опять же не длину строки (хотя вам может повезти с этим в 32-разрядных системах, где размер указателя соответствует вашей длине строки). Кроме того, вы пишете символы ANSI два раза, а не сначала пишете широкие символы, а затем символы ANSI, как вы, вероятно, намеревались, следуя вашему fprintf
примеру. То, что вы хотели написать, вероятно, было:
auto os = std::ofstream("temp_cpp.bin", std::ios::binary | std::ios::out);
const wchar_t* wide_word = L"wide char";
const char* word = "char";
std::wstring st(wide_word);
std::string str(st.begin(), st.end());
os.write((const char*)(st.c_str()), st.length() * sizeof(wchar_t));
os.write(word, strlen(word));
Это должно привести к тому же содержимому файла, что и в вашем fprintf
примере (но это не гарантируется, поскольку может зависеть от setLocale
). Или, без использования std::wstring
:
auto os = std::ofstream("temp_cpp.bin", std::ios::binary | std::ios::out);
const wchar_t* wide_word = L"wide char";
const char* word = "char";
os.write((const char*)wide_word, wcslen(wide_word) * sizeof(wchar_t));
os.write(word, strlen(word));
Другой вопрос, целесообразно ли записывать разные текстовые кодировки в один и тот же файл.
Комментарии:
1. Да, вы можете записывать байты
wchar_t
данных , но это не обязательно дает тот же эффект, что и запись широкой строки с помощью широко ориентированных функций / объектов ввода-вывода. Внутреннее представление не обязательно совпадает с внешним, и широкие функции ввода-вывода выполняют любой необходимый перевод.2. Спасибо; Я обновил ответ. Вам нужно будет прочитать байты обратно так же, как вы их записали. Я полагаю, что целью было записывать в один и тот же поток, не обязательно для получения того же результата,
fwprintf
что и .