2013-06-25 1 views
0

У меня есть этот код для сериализации/десериализации объектов класса в файл, и, похоже, он работает. Однако у меня есть два вопроса.Запись объекта класса в файл с использованием потоков

  1. Что делать, если вместо двух wstring «s (как у меня сейчас) я хочу иметь один wstring и один string член переменной в моем классе? (Я думаю, что в таком случае мой код не будет работать?).
  2. Наконец, внизу, в основном, когда я инициализирую s2.product_name_= L"megatex";, если вместо мегатекса я пишу что-то по-русски (например, s2.product_name_ = L "логин"), код больше не работает, как предполагалось.

Что может быть неправильным? Благодарю.

Вот код:

// ConsoleApplication3.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 
#include <iostream> 
#include <string> 
#include <fstream>  // std::ifstream 
using namespace std; 

// product 
struct Product 
{ 
    double price_; 
    double product_index_; 
    wstring product_name_; 
    wstring other_data_; 

    friend std::wostream& operator<<(std::wostream& os, const Product& p) 
    { 
     return os << p.price_ << endl 
        << p.product_index_ << endl 
        << p.product_name_ << endl 
        << p.other_data_ << endl; 
    } 

    friend wistream& operator>>(std::wistream& is, Product& p) 
    { 
     is >> p.price_ >> p.product_index_; 
     is.ignore(std::numeric_limits<streamsize>::max(), '\n'); 

     getline(is,p.product_name_); 
     getline(is,p.other_data_); 

     return is; 
    } 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    Product s1,s2; 

    s1.price_ = 100; 
    s1.product_index_ = 0; 
    s1.product_name_= L"flex"; 
    s1.other_data_ = L"dat001"; 

    s2.price_ = 300; 
    s2.product_index_ = 2; 
    s2.product_name_= L"megatex"; 
    s2.other_data_ = L"dat003"; 

    // write 
    wofstream binary_file("c:\\test.dat",ios::out|ios::binary|ios::app); 
    binary_file << s1 << s2; 
    binary_file.close(); 

    // read 
    wifstream binary_file2("c:\\test.dat"); 

    Product p; 
    while (binary_file2 >> p) 
    { 
     if(2 == p.product_index_){ 
      cout<<p.price_<<endl; 
      cout<<p.product_index_<<endl; 
      wcout<<p.product_name_<<endl; 
      wcout<<p.other_data_<<endl; 
     } 
    } 

    if (!binary_file2.eof()) 
     std::cerr << "error during parsing of input file\n"; 
    else 
     std::cerr << "Ok \n"; 

    return 0; 
} 

ответ

0

Что делать, если вместо того, чтобы два wstring (как у меня сейчас) я хочу иметь один wstring и переменную-член одна строка в моем классе? (Я думаю, что в таком случае мой код не будет работать?).

Есть все для вставки определяется char * для любого basic_ostream (ostream и wostream), так что вы можете использовать результат вызова функции c_str() члена для string члена. Например, если string член other_data_:

return os << p.price_ << endl 
      << p.product_index_ << endl 
      << p.product_name_ << endl 
      << p.other_data_.c_str() << endl; 

Корпус экстрактор является более сложным, так как вы будете читать wstring и обращенного к string. Самый простой способ сделать это просто чтение как wstring, а затем сужение каждого символа:

wstring temp; 
getline(is, temp); 
p.other_data_ = string(temp.begin(), temp.end()); 

Я не использую локали в этом примере, просто преобразование последовательности байтов (8 бит) в последовательность слов (16 бит) для вывода и противоположные (усекающие значения) для ввода. Это нормально, если вы используете символы ASCII или используете однобайтовые символы, и для вывода не требуется определенный формат (как Unicode).

В противном случае вам понадобится ручка с locale. locale дает культурную контекстуальную информацию для интерпретации строки (помните, что это всего лишь последовательность байтов, а не символы в смысле букв или символов, а карта между байтами и символом символа определяется locale). locale не очень простая в использовании концепция (человеческая культура не слишком). Как вы сами предполагаете, было бы лучше провести первое исследование о том, как это работает.

Во всяком случае, идея:

  1. Определить кодировку, используемую в строке и кодировку, используемую в файле (Unicode или UTF-16).
  2. Преобразование string с оригинальной кодировки в Юникод с использованием locale для вывода.
  3. Преобразование wstring s считывание из файла (в Юникоде) до string с использованием locale.

Наконец, ниже, в основном, когда я инициализировать s2.product_name_ = L "MEGATEX"; если вместо мегатекса я пишу что-то по-русски, то (например, s2.product_name_= L"логин"), код больше не работает, так как предназначен.

При определении массива wchar_t использованием L"", you'are действительно не указав строку в Unicode, так что массив из символов, не wchar_t. Я предполагаю, что предполагаемая работа s2.product_name_ сохранит имя в формате Unicode, но компилятор возьмет в этой строке char (как и без L) и конвертирует в wchar_t просто заполнение нулями наиболее значимого байта. Unicode не поддерживается в стандарте C++ до C++ 11 (и по-прежнему не поддерживается). Он работает только для символов ASCII, потому что они имеют одинаковую кодировку в Unicode (или UTF-8).

Для использования символов Unicode в статической строке вы можете использовать escape-символы: \uXXXX. Я знаю, что для каждого не-английского персонажа не очень удобно. Вы можете найти список символов Unicode на нескольких сайтах в Интернете. Например, в Википедии: http://en.wikipedia.org/wiki/List_of_Unicode_characters.

+0

Честно говоря, я не получил много того, что вы имели в виду. Не могли бы вы объяснить это более легко понять? Благодарю. –

+0

Какая часть? первый, второй или оба? – Gonmator

+0

Добавлены образцы, пытающиеся сделать проще – Gonmator