2008-10-02 3 views
5

У меня есть небольшая проблема с чтением данных из файла. Я хочу, чтобы иметь возможность читать wstring, а также кусок необработанных данных произвольного размера (размер в байтах).Как я могу прочитать двоичные данные из wfstream?

std::wfstream stream(file.c_str()); 

std::wstring comType; 
stream >> comType; 

int comSize; 
stream >> comSize; 

char *comData = new char[comSize]; 
memset(comData, 0, comSize); 
stream.read(comData, comSize); 
//error C2664 : 'std::basic_istream<_Elem,_Traits>::read' 
//   : cannot convert parameter 1 from 'char *' to 'wchar_t *' 

Возможно, я использую неправильные потоки или что-то в этом роде. В принципе, я хочу прочитать wstring, размер данных, которые следует (может быть любое количество байтов), а затем много байтов данных компонента. Очевидно, я не могу прочитать char, потому что шаблон предполагает wchar_t's.

Я могу читать wchar_t, но тогда я должен убедиться, что данные хранятся в соответствии с sizeof (wchar_t). В противном случае я мог бы портить поток. Сценарий будет, когда данные будут 15 байт. Мне нужно было бы прочитать 16 байтов, затем замаскировать нежелательный байт, искать поток до смещения 15 байтов (если возможно, с помощью wchar_t templated?), Чтобы читать следующий кусок данных.

Очевидно, что должен быть лучшим способом достижения того, что я пытаюсь сделать.

+2

Это только я или кто-то еще также читал WTFstream? :-) – VVS 2008-10-02 13:56:05

ответ

1

Учитывая ваши требования, я не думаю, что wfstream - это путь. Подумайте, используя что-то вроде следующего фрагмента кода.

#include "stdafx.h" 
#include <fstream> 
#include <iostream> 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    std::wstring str(L"hello"); 
    size_t size1 = str.length(); 
    char data[] = { 0x10, 0x20, 0x30 }; 
    size_t size2 = 3; 

    FILE* output = NULL; 
    if (_wfopen_s(&output, L"c:\\test.bin", L"wb") == 0) { 
     fwrite(&size1, sizeof(size_t), 1, output); 
     fwrite(str.c_str(), size1 * sizeof(wchar_t), 1, output); 
     fwrite(&size2, sizeof(size_t), 1, output); 
     fwrite(data, size2, 1, output); 

     fclose(output); 
    } 

    FILE* input = NULL; 
    if (_wfopen_s(&input, L"c:\\test.bin", L"rb") == 0) { 
     fread(&size1, sizeof(size_t), 1, input); 
     wchar_t* wstr = new wchar_t[size1 + 1]; 
     fread(wstr, size1 * sizeof(wchar_t), 1, input); 
     std::wstring str(wstr, size1); 
     delete[] wstr; 
     fread(&size2, sizeof(size_t), 1, input); 
     char* data1 = new char[size2]; 
     fread(data1, size2, 1, input); 

     std::wcout << str.c_str() << std::endl; 
     for (size_t i = 0; i < size2; ++i) { 
      std::wcout << std::hex << "0x" << int(data1[i]) << std::endl; 
     } 

     delete[] data1; 

     fclose(input); 
    } 

    return 0; 
} 

В этом выходы:

hello 
0x10 
0x20 
0x30 
+0

Я полагаю, что меняющаяся методология очень помогает. Спасибо за фрагменты. – Statement 2008-10-02 15:02:50

2

проблема с stream.read в том, что она использует wchar_t как "единица" символов с wfstream. Если вы используете fstream, он использует char как «блок символов».

Это будет работать, если вы хотите читать широкие символы:

wchar_t *comData = new wchar_t[comSize]; 
stream.read(comData, comSize); 

также 15 байт данных не могут быть считаны с широким потоком, так как наименьшая единица является по меньшей мере 2bytes (смотри ниже), поэтому вы можете читать только фрагменты szwwof (wchar_t) * n.

Но если вы обеспокоены переносимостью приложения wfstream/wchar_t, возможно, это не лучшее решение, потому что нет стандарта, как широко распространен wchar_t (например, на windows wchar_t 16 бит на многих системах unix/linux 32bit).

Вторая проблема с сохранением текста в виде широких символов - это endianess, я бы предложил использовать UTF-8 для хранения текста.

+0

Хорошие очки. Некоторое время назад я отказался от широких символов. Кодирование заняло слишком много времени, код стал неясным, и мы решили, что проблема не связана с регулярными символами для строк. – Statement 2008-10-02 15:02:14

0
# ifdef UNICODE 
#  define tfstream wfstream 
# else 
#  define tfstream fstream 
# endif 

tfstream fs(_T("filename.bin"), tfstream::binary); 
byte buffer[1023]; 
fs.read(buffer, sizeof(buffer)) 

думаю, _T ("filename.bin") и tfstream являются выражением UI; буфер и read() - выражение DATA LOGIC. wfstream НЕ должен ограничивать буфер типом wchar_t. Пользовательский интерфейс НЕ должен смешиваться с DATA LOGIC! wfstream сделать не то, что здесь

Смежные вопросы