Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++
I have this code to serialize/deserialize class objects to file, and it seems to work.
However, I have two questions.
 
1. What if instead two wstring's (as I have now) I want to have one wstring and one string member
variable in my Product class? (I think in such case my code won't work?).
 
2. Finally, below, in main, when I initialize s2.product_name_= L"megatex"; if instead of megatex I write something in Russian say (e.g., s2.product_name_= L"логин"), the code doesn't work anymore as intended.
 
What can be wrong? Thanks.
 
Here is code:
    // 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; // error 1
        }
    
        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_); // error 5, also error 2
    		
            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;
    }
 

Posted 25-Jun-13 5:10am
Edited 25-Jun-13 21:42pm
v2
Comments
nv3 at 25-Jun-13 11:14am
   
Can you show the compilation errors you get when you use string instead of wistream? I assume they are with the getline calls?
 
And what exactly goes wrong when you assign a cyrillic string to your product name?
Dan page at 26-Jun-13 2:22am
   
This is one error:
 
- (from operator <<) Error 1 error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const std::string' (or there is no acceptable conversion)
 
this is second:
 
- Error 5 error C2780: 'std::basic_istream<_Elem,_Traits> &std::getline(std::basic_istream<_Elem,_Traits> &&,std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem)' : expects 3 arguments - 2 provided
 
The above one is related to getline
Sergey Alexandrovich Kryukov at 26-Jun-13 2:31am
   
In what lines? Don't put it in comments. Use "Improve question" and add comments to the code next to the offending lines...
—SA
Dan page at 26-Jun-13 2:43am
   
like this?
 
ps. this is error2:
 
Error 2 error C2782: 'std::basic_istream<_Elem,_Traits> &std::getline(std::basic_istream<_Elem,_Traits> &,std::basic_string<_Elem,_Traits,_Alloc> &)' : template parameter '_Elem' is ambiguous c:\users\documents\visual studio 2012\projects\consoleapplication3\consoleapplication3\consoleapplication3.cpp 34 1 ConsoleApplication3
 
some other parts of code I managed to modify. I get two or three other errors to but they are same as I posted above, and at same lines.
Sergey Alexandrovich Kryukov at 26-Jun-13 2:45am
   
Why you don't want to do what I suggested?
—SA
Dan page at 26-Jun-13 2:53am
   
I don't mind, but which do you mean?
This: >>"convert all kinds of strings to array of bytes using UTF-8 Unicode encoding."?
Yes, but how? You mean use std:string with UTF-8? I am ok with it just could you explain bit more how/why that would work.
 
I am reading some links you gave me now.
Sergey Alexandrovich Kryukov at 26-Jun-13 9:57am
   
Please see:
http://mariusbancila.ro/blog/2008/10/20/writing-utf-8-files-in-c/
 
—SA
nv3 at 26-Jun-13 3:04am
   
Ok, Dan. That shows that your C++ libraries do have no automatic conversion of a string to the wistream. You could either write that yourself if you are intending to use that often or simply convert the string to a wstring before streaming it out.
 
In the long run I would however prefer a more sophisticated serialization method, like the one in the boost library that Sergey recommended. Reason: You want to be compatible when your data structure changes and you want to be able to read serialized data that was written some years ago.

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

First of all, you can mix wstring and string (why not, in principle?), but you don't have to, because you can have the following universal approach: convert all kinds of strings to array of bytes using UTF-8 Unicode encoding. This encoding codes a code point below 256 as one byte, and pack others in 2-4 byte words when it is required by its algorithm. This way, you would have universal persistence method for all strings.
 
I would advice to look at the comprehensive way of C++ object persistence: boost serialization: http://www.boost.org/doc/libs/1_53_0/libs/serialization/doc/index.html[^].
 
[EDIT]
 
In response to the follow-up question:
 
Before you can move any further, you really need to learn more about Unicode:
http://en.wikipedia.org/wiki/Unicode[^],
http://en.wikipedia.org/wiki/Code_point[^],
http://en.wikipedia.org/wiki/Utf-8[^],
http://en.wikipedia.org/wiki/Byte_order_mark[^],
http://unicode.org/[^],
http://www.unicode.org/faq/utf_bom.html[^].
 
If you have any questions on these topics, you are welcome to ask, but I expect you to learn general concepts by yourself first.
 
—SA
  Permalink  
v3
Comments
Dan page at 25-Jun-13 10:36am
   
>>"First of all, you can mix wstring and string (why not, in principle?)"
Hi, because if I declare one of my wstrings above as a string, I get compilation errors.
 
>>"convert all kinds of strings to array of bytes using UTF-8 Unicode encoding. "
Can you explain a bit more details on this how? and also bit more information on the second part of your first paragraph.
Sergey Alexandrovich Kryukov at 25-Jun-13 10:45am
   
Well, fix the compilation error first, this is way easier then persistence... :-)
It is not related to your problem at all.
—SA
Dan page at 25-Jun-13 10:52am
   
It's not easy to fix those issues, that's the problem ...
Sergey Alexandrovich Kryukov at 25-Jun-13 16:04pm
   
Well, add a comment to the exact line which causes compilation error, add complete error information, let's see...
—SA
Dan page at 26-Jun-13 2:23am
   
I posted errors above, below nav3's comment
Sergey Alexandrovich Kryukov at 25-Jun-13 10:46am
   
You need to learn about Unicode and UTFs more...
Please see the updated answer, after [EDIT].
—SA
Dan page at 25-Jun-13 10:55am
   
Hi, thanks although I got familiar myself with Unicode and encodings already (more or less). e.g., Unicode stores characters in certain format, called codepoint -- UTF 8 for example is encoding then which indicates how Unicode should be interpreted. but I'll look at your links, seems unicode support with c++ isn't trivial
Sergey Alexandrovich Kryukov at 25-Jun-13 16:07pm
   
Got familiar, you think so? Looking at your comment, I wouldn't be so sure. For example, "code point" has nothing to do with interpretation. Difficult or not — libraries do all required operations.
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 Kornfeld Eliyahu Peter 275
1 Maciej Los 204
2 Sergey Alexandrovich Kryukov 200
3 King Fisher 185
4 OriginalGriff 183
0 OriginalGriff 6,223
1 DamithSL 4,724
2 Maciej Los 4,196
3 Kornfeld Eliyahu Peter 3,894
4 Sergey Alexandrovich Kryukov 3,496


Advertise | Privacy | Mobile
Web02 | 2.8.141220.1 | Last Updated 26 Jun 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100