2008-10-02 22 views
5

Mam niewielki problem z odczytaniem danych z pliku. Chcę móc czytać wstringa, a także fragment surowych danych o dowolnym rozmiarze (rozmiar jest w bajtach).Jak mogę odczytać dane binarne z 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 *' 

Być może używam niewłaściwych strumieni lub czegoś podobnego. Zasadniczo chcę przeczytać ciąg znaków, wielkość podanych danych (która może być dowolną liczbą bajtów), a następnie tyle bajtów danych składowych. Oczywiście nie mogę odczytać chara, ponieważ szablon przyjmuje wchar_t.

Potrafię odczytać wchar_t, ale muszę się upewnić, że dane są przechowywane zgodnie z sizeof (wchar_t). W przeciwnym razie mógłbym zepsuć strumień. Scenariusz miałby miejsce, gdy dane mają 15 bajtów. Musiałbym odczytać 16 bajtów, następnie zamaskować niechciany bajt, wyszukać strumień do 15 bajtów offsetu (jeśli to możliwe z wchar_t w templated?), Aby móc odczytać następny fragment danych.

Oczywiście, należy powinien być ładniejszy sposób osiągnięcia tego, co próbuję zrobić.

+2

Czy to tylko ja, czy też ktoś jeszcze przeczytał WTFstream? :-) – VVS

Odpowiedz

1

Biorąc pod uwagę twoje wymagania, nie sądzę, że wfstream jest drogą do zrobienia. Osoba rozważająca użycie podobnego fragmentu kodu.

#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; 
} 

This wyjścia:

hello 
0x10 
0x20 
0x30 
+0

Przypuszczam, że zmiana metodologii bardzo pomaga. Dziękuję za fragmenty. – Statement

2

problem z stream.Read jest to, że używa wchar_t jako "jednostki znaków" z wfstream. Jeśli używasz fstream, to używa on char jako "jednostki znaków".

to będzie działać, jeśli chcesz przeczytać szerokie znaki:

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

również 15 bajtów danych nie można odczytać z szerokim strumieniem, ponieważ najmniejsza jednostka jest co najmniej 2 bajty (patrz poniżej), więc możesz tylko przeczytać fragmenty sizwof (wchar_t) * n.

Ale jeśli martwisz się przenośnością aplikacji, wfstream/wchar_t może nie jest najlepszym rozwiązaniem, ponieważ nie ma standardu jak szeroki jest wchar_t (np. W systemach wchar_t jest 16-bitowy w wielu systemach unix/linux jest 32-bitowy).

Drugi problem z przechowywaniem tekstu jako szerokiego znaku jest bezwarunkowy, sugerowałbym użycie UTF-8 do przechowywania tekstu.

+0

Dobre punkty. Porzuciłem szeroko wszystkie znaki razem jakiś czas temu. Kodowanie zajęło zbyt wiele czasu, kod stał się niejasny i uznaliśmy, że nie ma większego problemu z trzymaniem się zwykłych znaków na strunach. – Statement

+0

Wifstream odczyta wąskie znaki ze strumienia. (chyba, że ​​czytasz surowe znaki, jak sugerujesz). Wszyscy oczekują od niego szerokich znaków, ale w rzeczywistości tak nie jest. Możesz odczytywać UTF-8 używając na przykład wifstream i aspektu kodeków do konwersji na odbiorców. Obsługa plików UTF-16 jest bardziej skomplikowana niż myślisz. – Pete

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)) 

Myślę, że _T ("filename.bin") i tfstream są wyrażeniem interfejsu użytkownika; bufor i read() to wyrażenie LOGIC DANYCH. wfstream NIE może ograniczać bufora do typu wchar_t. Interfejs użytkownika NIE może mieszać się z LOGIKĄ DANYCH! wfstream robisz coś niewłaściwego