patterncppMinor
Writing/reading data structure to a file using C++
Viewed 0 times
readingfilewritingstructureusingdata
Problem
I wrote some piece of code which reads and write multiple data structures on a file
using C++. I would be grateful to get your feedback on what you think about the code (it works at least when I tested). Thanks.
using C++. I would be grateful to get your feedback on what you think about the code (it works at least when I tested). Thanks.
#include "stdafx.h"
#include
#include
#include
using namespace std;
// data structure to be written to a file
struct WebSites
{
char SiteName[100];
int Rank;
}s1,s2,s3,s4;
int _tmain(int argc, _TCHAR* argv[])
{
strcpy(s1.SiteName, "www.ppp.com");
s1.Rank = 0;
strcpy(s2.SiteName, "www.rrr.com");
s2.Rank = 111;
strcpy(s3.SiteName, "www.code.com");
s3.Rank = 123;
strcpy(s4.SiteName, "www.yahoo.com");
s4.Rank = 14;
// write
fstream binary_file("c:\\test.dat",ios::out|ios::binary|ios::app);
binary_file.write(reinterpret_cast(&s1),sizeof(WebSites));
binary_file.write(reinterpret_cast(&s2),sizeof(WebSites));
binary_file.write(reinterpret_cast(&s3),sizeof(WebSites));
binary_file.write(reinterpret_cast(&s4),sizeof(WebSites));
binary_file.close();
// Read data
fstream binary_file2("c:\\test.dat",ios::binary|ios::in| ios::ate );
int size = binary_file2.tellg();
for(int i = 0; i(&p_Data),sizeof(WebSites));
cout<<p_Data.SiteName<<endl;
cout<<"Rank: "<< p_Data.Rank<<endl;
}
binary_file2.close();
return 0;
}Solution
The trouble with writing binary blobs is that they lead to brittle storage.
The stored objects have a tendency to break over time as the assumptions you make about the hardware no longer hold true (in this case that the
It has become more standard therefore to use a method know as serialization. In this you convert the object to a format that is hardware agnostic (and usually human readable).
Note: Binary blobs have advantages. But you must weigh those against the brittleness. Therefore your first choice should be serialization (unless you have specific requirements that prevents this). Then look at binary Blobs only after you have shown that serialization has too much overhead (unlikely for most situations, but it is a possibility).
In C++ you would do this using the
I would re-write your code as:
Now you can write your code like this:
The stored objects have a tendency to break over time as the assumptions you make about the hardware no longer hold true (in this case that the
sizeof(int) is constant and the endianess of int will not change).It has become more standard therefore to use a method know as serialization. In this you convert the object to a format that is hardware agnostic (and usually human readable).
Note: Binary blobs have advantages. But you must weigh those against the brittleness. Therefore your first choice should be serialization (unless you have specific requirements that prevents this). Then look at binary Blobs only after you have shown that serialization has too much overhead (unlikely for most situations, but it is a possibility).
In C++ you would do this using the
operator>.I would re-write your code as:
struct WebSites
{
std::string siteName;
int rank;
WebSite()
: siteName("")
, rank(0)
{}
WebSite(std::string const& siteName, int rank)
: siteName(siteName)
, rank(rank)
{}
void swap(WebSites& other) throws()
{
std::swap(rank, other.rank);
std::swap(siteName, other.siteName);
}
};
std::ostream& operator>(std::istream& stream, WebSites& data)
{
WebSite tmp;
std::size_t size;
if (stream >> tmp.rank >> size)
{
tmp.siteName.resize(size);
if (stream.read(tmp.siteName[0], size)
{
data.swap(tmp);
}
}
return stream;
}Now you can write your code like this:
int _tmain(int argc, _TCHAR* argv[])
{
WebSite s1("www.ppp.com", 0);
WebSite s2("www.rrr.com", 111);
WebSite s3("www.code.com", 123);
WebSite s4("www.yahoo.com", 14);
// write
fstream binary_file("c:\\test.dat",ios::out|ios::binary|ios::app);
binary_file > p_Data)
{
cout v;
std::copy(std::istream_iterator(binary_file3),
std::istream_iterator(),
std::back_inserter(v)
);
binary_file3.close();
}Code Snippets
struct WebSites
{
std::string siteName;
int rank;
WebSite()
: siteName("")
, rank(0)
{}
WebSite(std::string const& siteName, int rank)
: siteName(siteName)
, rank(rank)
{}
void swap(WebSites& other) throws()
{
std::swap(rank, other.rank);
std::swap(siteName, other.siteName);
}
};
std::ostream& operator<<(std::ostream& stream, WebSites const& data)
{
stream << data.rank << " "
<< data.siteName.size() << ":"
<< data.siteName;
return stream;
}
std::istream& operator>>(std::istream& stream, WebSites& data)
{
WebSite tmp;
std::size_t size;
if (stream >> tmp.rank >> size)
{
tmp.siteName.resize(size);
if (stream.read(tmp.siteName[0], size)
{
data.swap(tmp);
}
}
return stream;
}int _tmain(int argc, _TCHAR* argv[])
{
WebSite s1("www.ppp.com", 0);
WebSite s2("www.rrr.com", 111);
WebSite s3("www.code.com", 123);
WebSite s4("www.yahoo.com", 14);
// write
fstream binary_file("c:\\test.dat",ios::out|ios::binary|ios::app);
binary_file << s1 << s2 << s3 << s4;
binary_file.close();
// Read data
fstream binary_file2("c:\\test.dat",ios::binary|ios::in| ios::ate );
WebSites p_Data;
while(binary_file2 >> p_Data)
{
cout << p_Data.SiteName << endl;
cout << "Rank: "<< p_Data.Rank << endl;
}
binary_file2.close();
// Read data into a vector
fstream binary_file3("c:\\test.dat",ios::binary|ios::in| ios::ate );
std::vector<WebSites> v;
std::copy(std::istream_iterator<WebSites>(binary_file3),
std::istream_iterator<WebSites>(),
std::back_inserter(v)
);
binary_file3.close();
}Context
StackExchange Code Review Q#26344, answer score: 8
Revisions (0)
No revisions yet.