Reading and Writing binary files

Hello,
First the code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  struct Product { char name[200]; int code; double price; }; 
void readDataBinary (const char* name , Product* products,int& count)
{
	ifstream inFile;
	inFile.open(name,ios::binary);
	
	while(inFile)
	{
		if(count>0)
		{
			Product* temp = new Product [count];
			for(int i=0;i<count;i++)
			{
				temp[i]=products[i];
			}
			delete[] products;
			products = new Product [count + 1];
			for(int i=0;i<count;i++)
			{
				products[i]=temp[i];
			}
			inFile.read((char*)&products[count],sizeof(products[count]));
			delete[] temp;
			count++;
		}
		else
		{
			inFile.read((char*)&products[0],sizeof(products[0]));
			count++;
		}
	} 
}

void fileWriteBin(const char* name, Product* prod, int size)
{
	ofstream outFile;
	outFile.open(name,ios::binary);
	for(int i=0;i<size;i++)
	{
      outFile.write((const char*)&prod[i],sizeof(prod[i]));
	}
	outFile.close();
}


The problem is if I write to the file 3 products. When I try to read them it takes 4 products. The while(inFile) returns true 4 times instead of only 3 and this makes 1 more product that I don't need because it has no true values.

Also when readDataBinary ends and returns to the main function if I take prod[0[.price it gives me unreal value. Is it the same problem or I don't use the right methods ?
Use std::vector<> http://www.mochima.com/tutorials/vectors.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <fstream>
#include <vector>
#include <iostream>

struct Product { char name[200]; int code; double price; };

void fileWriteBin( const char* file_name, const std::vector<Product>& prod )
{
    std::ofstream file( file_name, std::ios::binary ) ;
    
    // note: since Product is a pod, its first member (name) must be at an offset of zero.
    for( const Product& p : prod ) file.write( p.name, sizeof(p) ) ;

}

std::vector<Product> readDataBinary( const char* file_name )
{
    std::vector<Product> prod ;
    std::ifstream file( file_name, std::ios::binary ) ;

    Product temp ;
    while( file.read( temp.name, sizeof(temp) ) ) // canonical; for every Product read from the file
        prod.push_back(temp) ; // add it to the vector

    return prod ;
}

int main()
{
    const char* const file_name = "products.bin" ;

    {
        std::vector<Product> prod
        {
            Product{ "Honey", 1, 12.34 },
            Product{ "Coffee", 2, 56.78 },
            Product{ "Claret", 3, 90.12 }
        };

        fileWriteBin( file_name, prod ) ;
    }

    {
        std::vector<Product> prod = readDataBinary(file_name) ;
        for( const Product& p : prod )
            std::cout << p.name << ' ' << p.code << ' ' << p.price << '\n' ;
    }
}

http://coliru.stacked-crooked.com/a/3bb75a131534a651
Thank you very much.

So everytime I want to write/read to/from file I have to use the first member with the size of the whole structure?

Also this for for( const Product& p : prod ) I see this type of for for first time. Does it mean for every product in prod ? If it is, it's super useful and easy "for". Thank you !
> So everytime I want to write/read to/from file
> I have to use the first member with the size of the whole structure?

In this particular case, it works. Because the the first member, in order of declaration is an array of char. (For a pod, the address of the first non-static member is same as the address of the object.)

The general idiom, which will always work with any pod is:

1
2
for( const Product& p : prod ) 
    file.write( reinterpret_cast<const char*>( &p ), sizeof(p) ) ;


1
2
3
Product temp ;
while( file.read( reinterpret_cast<char*>( &temp ), sizeof(temp) ) ) 
{ /* ... */ }

Stick with that general version; I was just being unnecessarily cute with a special case.



> Also this for for( const Product& p : prod ) I see this type of for for first time.
> Does it mean for every product in prod ?

Yes.

It is the range-based for loop introduced in C++11.
http://www.stroustrup.com/C++11FAQ.html#for
Topic archived. No new replies allowed.