Чтение бинарных данных из std::wifstream

134
18 декабря 2020, 04:50

Необходимо считать в std::string байты файла. Одно из требований: поддержка юникодных имен файлов. Реализовал следующую функцию:

std::string ReadFileBinary(const std::filesystem::path& filename)
{
    std::wifstream file(filename, std::ios::binary);
    if (!file.is_open())
    {
        // выброс проектного исключения
    }
    std::stringstream ss;
    ss << file.rdbuf();
    std::string binary_data((const char*)ss.str().c_str(), ss.str().size());
    return binary_data;
}

Далее реализовл тестирование следующим образом (google test):

TEST(string_utils, TestReadFileBinary) 
{
    char c_file_data[] = { 0x60, 0xED, 0xDA, 0xCD, 0xAB, 0xDD, 0xDD, 0xDD, 0xCE, 0xDA, 0xBC, 0xD1, 0x24 };
    std::string file_data(c_file_data, sizeof(c_file_data));
    std::string readed_file_data = 
    ReadFileBinary("test_read_file_binary.bin");
    EXPECT_EQ(file_data, readed_file_data);
}

Содержимое файла test_read_file_binary.bin:

Тест проваливается со следующей ошибкой:

error:       Expected: file_data
      Which is: "`\xED\xDA\xCD\xAB\xDD\xDD\xDD\xCE\xDA\xBC\xD1$"
To be equal to: readed_file_data
      Which is: "010FF3B8"

При работе с ifstream а не wifstream считывание производится корректно, но не обрабатываются юникодные имена файлов.

Answer 1

После анализа пришел к выводу, что средствами STL данный функционал реализовать невозможно ввиду отсутствия адекватной поддержки Unicode со стороны С++. Реализовал с помощью WinAPI. Код:

void WriteFileBinary(const std::filesystem::path& filename, const std::string &data)
{
    DWORD creation_disposition = exists(filename) ? TRUNCATE_EXISTING : CREATE_NEW;
    DWORD bytes_to_write = data.size();
    DWORD bytes_written = 0;
    HANDLE h_file = CreateFileW
    (
        filename.generic_wstring().c_str(),
        GENERIC_WRITE,
        0,
        nullptr,
        creation_disposition,
        FILE_ATTRIBUTE_NORMAL,
        nullptr
    );
    if (h_file == INVALID_HANDLE_VALUE)
    {
        // throw
    }
    bool write_status = WriteFile
    (
        h_file,
        data.c_str(),
        bytes_to_write,
        &bytes_written,
        nullptr
    );
    if (!write_status)
    {
        CloseHandle(h_file);
        // throw
    }
    if (bytes_written != bytes_to_write)
    {
        CloseHandle(h_file);
        // throw
    }
    CloseHandle(h_file);
}
std::string ReadFileBinary(const std::filesystem::path& filename)
{
    HANDLE h_file = CreateFileW
    (
        filename.generic_wstring().c_str(), 
        GENERIC_READ, 
        0, 
        nullptr, 
        OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL, 
        nullptr
    );
    if (h_file == INVALID_HANDLE_VALUE)
    {
        // throw
    }
    DWORD file_len = file_size(filename);
    DWORD bytes_read = 0;
    char *file_data = (char*)malloc(file_len);
    if (file_data == nullptr)
    {
        CloseHandle(h_file);
        // throw
    }
    bool read_status = ReadFile
    (
        h_file,
        file_data,
        file_size(filename),
        &bytes_read,
        nullptr
    );
    if (!read_status)
    {
        free(file_data);
        CloseHandle(h_file);
        // throw
    }
    if (bytes_read != file_len)
    {
        free(file_data);
        CloseHandle(h_file);
        // throw
    }
    std::string result(file_data, file_len);
    CloseHandle(h_file);
    free(file_data);
    return result;
}
READ ALSO
Примеры указателей в с++ [закрыт]

Примеры указателей в с++ [закрыт]

Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы он был сосредоточен только на одной проблеме

92
Qt5: как обновить данные в QTableWidget

Qt5: как обновить данные в QTableWidget

Есть некоторая таблица в которую из базы данных через промежуточную структуру подгружаются данные(вектор объектов класса)В структуре данные...

106
Звёздочка (*) перед классом

Звёздочка (*) перед классом

Что означает такая конструкция?

93