2008-10-02 29 views
5

Tôi có một vấn đề nhỏ khi đọc dữ liệu từ tệp. Tôi muốn có thể đọc wstring, cũng như một đoạn dữ liệu thô có kích thước tùy ý (kích thước bằng byte).Làm cách nào để đọc dữ liệu nhị phân từ 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 *' 

Có lẽ tôi đang sử dụng các luồng sai hoặc một thứ gì đó dọc theo các dòng đó. Về cơ bản, tôi muốn đọc một wstring, kích thước của dữ liệu theo sau (có thể là bất kỳ số byte nào), theo sau là nhiều byte dữ liệu thành phần. Rõ ràng, tôi không thể đọc của char vì mẫu giả định của wchar_t.

Tôi có thể đọc wchar_t's nhưng sau đó tôi phải đảm bảo dữ liệu được lưu trữ theo sự liên kết của sizeof (wchar_t). Nếu không, tôi có thể sẽ làm hỏng luồng. Một kịch bản sẽ là khi dữ liệu là 15 byte. Tôi sẽ phải đọc 16 byte, sau đó mặt nạ byte không mong muốn, tìm kiếm các dòng để 15 byte bù đắp (nếu có thể với wchar_t templated?) Để có thể đọc đoạn dữ liệu tiếp theo.

Rõ ràng, có nên là một cách hay hơn để đạt được những gì tôi đang cố gắng làm.

+2

Chỉ là tôi hay ai đó khác cũng đọc WTFstream? :-) – VVS

Trả lời

1

Xem xét các yêu cầu của bạn Tôi không nghĩ rằng wfstream là con đường để đi. Người xem xét sử dụng nội dung nào đó giống như đoạn mã sau.

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

đầu ra này:

hello 
0x10 
0x20 
0x30 
+0

Tôi cho rằng phương pháp thay đổi sẽ giúp ích rất nhiều. Cảm ơn các đoạn trích. – Statement

2

vấn đề với stream.read là nó sử dụng wchar_t là "đơn vị nhân vật" với wfstream. Nếu bạn sử dụng fstream nó sử dụng char là "đơn vị ký tự".

Điều này sẽ có tác dụng nếu bạn muốn đọc các ký tự rộng:

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

Ngoài ra 15 byte dữ liệu không thể được đọc với một dòng suối rộng, bởi vì đơn vị nhỏ nhất là ít nhất 2bytes (xem dưới đây), vì vậy bạn chỉ có thể đọc các phần của sizwof (wchar_t) * n. Nhưng nếu bạn lo ngại về tính di động của ứng dụng wfstream/wchar_t có lẽ không phải là giải pháp tốt nhất vì không có chuẩn wchar_t rộng (ví dụ trên windows wchar_t là 16bit trên nhiều hệ thống unix/linux, nó là 32bit).

Vấn đề thứ hai với lưu trữ văn bản dưới dạng ký tự rộng là endianess, tôi khuyên bạn nên sử dụng UTF-8 để lưu trữ văn bản.

+0

Điểm tốt. Tôi đã từ bỏ những ký tự rộng rãi cùng nhau một thời gian trước đây. Mã hóa mất quá nhiều thời gian, mã đã không rõ ràng, và chúng tôi quyết định không phải là một vấn đề để gắn bó với các ký tự thông thường cho chuỗi. – Statement

+0

Wifstream sẽ đọc các ký tự hẹp từ luồng. (trừ khi bạn đọc chars thô, như bạn đề nghị). Mọi người hy vọng nó đọc các ký tự rộng, nhưng thực tế là nó không có. Bạn có thể đọc UTF-8 bằng cách sử dụng một khía cạnh wifstream và codecvt để chuyển đổi thành wchars, chẳng hạn. Việc xử lý các tệp UTF-16 phức tạp hơn bạn nghĩ. – 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)) 

Tôi nghĩ, _T ("filename.bin") và tfstream là biểu thức giao diện người dùng; bộ đệm và biểu thức read() là biểu thức DATA LOGIC. wfstream KHÔNG được giới hạn bộ đệm cho kiểu wchar_t. Giao diện người dùng KHÔNG được trộn với DATA LOGIC! wfstream làm điều sai ở đây

Các vấn đề liên quan