![]() |
|
Reading from a binary file |
AmnesiA
Member #15,195
June 2013
![]() |
I'm fairly new to C++ as a whole and despite it being pretty straight forward, I am having trouble wrapping my head around binary files. In my practice program I'm saving program settings (width and height) to a binary file and then reading them (to load them). The saving part looks like this: int width = 640, height = 480; myfile.write( reinterpret_cast<const char*>(&width), sizeof(width)); myfile.write( reinterpret_cast<const char*>(&height), sizeof(height)); As far as I can tell this part works just fine. Opening the file in notepad shows that it saves as (extended characters). I'm having trouble reading the file though. I read it with this code: ifstream::pos_type size; size = myifile.tellg(); char* memblock; memblock = new char [size]; myifile.seekg( 0, ios::beg); myifile.read( memblock, size); myifile.close(); and then I assume the entire file is saved to memblock so I attempt to parse that by reading (*memblock) and (*(memblock + 1)). However, this shows me that those two values are 96 and 45. I'm pretty sure it's my parsing that's incorrect but I'm not sure how to amend this. ======================= |
Thomas Fjellstrom
Member #476
June 2000
![]() |
memblock is a pointer to char, and chars are typically one byte. And you're saving integers with are likely 4 bytes. So what you're getting are the first two bytes of the first thing you wrote. One way to fix it would be making memblock a pointer to integers and allocating two integers ( new int [2] or new int [size / sizeof(int)] ). Now using *memblock and *(memblock+1) will work. You'll want to look into endianness though. make sure you're writing/reading numbers to the file in the same format regardless of platform. -- |
AmnesiA
Member #15,195
June 2013
![]() |
For all of this file writing/reading the arguments require a char* but if I'm only writing characters what's the advantage to using binary over a text file? I saw that reinterpret_cast isn't portable so that causes problems so what's the other option for writing an integer or other data type to a binary file? I think knowing that would solve my other problem which is that reading the file also requires a char* and I can't get it to read the original values that I entered. If I reinterpret_cast<char*>(memblock) then the two integer values that memblock gives me are random garbage values. ifstream::pos_type size; size = myifile.tellg(); int* memblock; memblock = new int [size / sizeof(int)]; myifile.seekg( 0, ios::beg); myifile.read( reinterpret_cast<char*>(memblock), size); cout << memblock[1] << endl; myifile.close(); cout << memblock[0] << " | " << memblock[1] << endl; tl;dr How do I read/write integer values to a binary file when the functions require char*? ======================= |
Thomas Fjellstrom
Member #476
June 2000
![]() |
AmnesiA said: For all of this file writing/reading the arguments require a char* but if I'm only writing characters what's the advantage to using binary over a text file? A char is just a data storage type. It's equal to one byte, which is the smallest addressable component in most modern systems. When those functions use char, they do not care what you send to it, so long as the length is sent properly. Assuming your file is 8 bytes or larger, and the file was written in the same way, you code looks like it should work. Maybe paste a full runnable simple example of the code that shows the problem. -- |
AmnesiA
Member #15,195
June 2013
![]() |
1#include<iostream>
2#include<fstream>
3
4using namespace std;
5
6int width, height;
7int readwidth, readheight;
8
9int main(){
10 //File write
11 int width = 640, height = 480;
12 cout << "Saving settings...\n";
13 ofstream myfile;
14 myfile.open( "settings.ex", ios::out | ios::trunc | ios::binary);
15 if( myfile.is_open()){
16 myfile.write( reinterpret_cast<const char*>(&width), sizeof(width));
17 myfile.write( reinterpret_cast<const char*>(&height), sizeof(height));
18 myfile.close();
19 cout << "Complete!\n";
20 }else{
21 cout << "WARNING: Unable to save settings!\n";
22 }
23
24 //File read
25 cout << "\nReading settings...\n";
26 ifstream myifile;
27 myifile.open( "settings.ex", ios::in | ios::binary);
28 if( myifile.is_open()){
29 ifstream::pos_type size;
30 size = myifile.tellg();
31 int* memblock;
32 memblock = new int [size / sizeof(int)];
33 myifile.seekg( 0, ios::beg);
34 myifile.read( reinterpret_cast<char*>(memblock), size);
35 myifile.close();
36 cout << memblock[0] << " | " << memblock[1] << endl;
37 }else{
38 cout << "WARNING: Unable to read settings!\n";
39 }
40
41 return 0;
42}
======================= |
Thomas Fjellstrom
Member #476
June 2000
![]() |
1#include <errno.h>
2#include <string.h>
3#include <stdio.h>
4#include <allegro5/allegro5.h>
5
6
7int main(int argc, char **argv)
8{
9 ALLEGRO_FILE *f = NULL;
10 int data[] = { 1234, 5678 };
11
12 printf("data: %i, %i\n", data[0], data[1]);
13
14 al_init();
15
16 f = al_fopen("settings.ex", "w");
17 if(!f)
18 {
19 printf("Failed to open file for writing: %s\n", strerror(al_get_errno()));
20 return -1;
21 }
22
23 if(al_fwrite32le(f, data[0]) != sizeof(data[0]))
24 {
25 printf("failed to write data[0] to file: %s\n", strerror(al_get_errno()));
26 return -1;
27 }
28
29 if(al_fwrite32le(f, data[1]) != sizeof(data[1]))
30 {
31 printf("failed to write data[1] to file: %s\n", strerror(al_get_errno()));
32 return -1;
33 }
34
35 al_fclose(f);
36
37 f = al_fopen("settings.ex", "r");
38 if(!f)
39 {
40 printf("failed to open file for reading: %s\n", strerror(al_get_errno()));
41 return -1;
42 }
43
44 data[0] = al_fread32le(f);
45 data[1] = al_fread32le(f);
46
47 al_fclose(f);
48
49 printf("data: %i, %i\n", data[0], data[1]);
50 return 0;
51}
And due to using the allegro specific integer read/write functions, you don't have to worry about twiddling bits to make sure your integers are saved and loaded properly. Checking for errors from the al_fread32le calls is left as an exercise for the reader. Append: I figured it out. You're calling tellg [2], but you never actually seeked to the end of the file with myifile.seekg(0, ostream::end) or whatever. References
-- |
AmnesiA
Member #15,195
June 2013
![]() |
Ohhhh duhh. Thank you, and I appreciate the alternate method using allegro, much more helpful than I was expecting! ======================= |
LennyLen
Member #5,313
December 2004
![]() |
AmnesiA said: Thank you, and I appreciate the alternate method using allegro, much more helpful than I was expecting! Allegro's routines are very useful, since they take care of endianness for you.
|
|