Использование одного и того же объекта для записи wide char и char для записи в один и тот же файл

#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 что и .