This is basically the part of the code that i used to store the entire file, and works well ... but when i tryed to store a integer bigger than 120 or something like that the program writes seems like a bunch of trash and not the integer that i want. Any tips ? I am an college student and dont have a clue whats happening.
int* temp
temp = (int*) malloc (sizeof(int));
*temp = atoi( it->valor[i].c_str() );
//Writes the integer in 4 bytes
fwrite(temp, sizeof (int), 1, arq);
if( ferror(arq) ){
printf("\n\n Error \n\n");
exit(1);
}
free(temp);
I've already checked the atoi part and it really returns the number that I want to write.
I changed and added some code and it works fine:
#include <iostream>
using namespace std;
int main()
{
int* temp;
FILE *file;
file = fopen("file.bin" , "rb+"); // Opening the file using rb+ for writing
// and reading binary data
temp = (int*) malloc (sizeof(int));
*temp = atoi( "1013" ); // replace "1013" with your string
//Writes the integer in 4 bytes
fwrite(temp, sizeof (int), 1, file);
if( ferror(file) ){
printf("\n\n Error \n\n");
exit(1);
}
free(temp);
}
Make sure you are opening the file with the correct parameters, and that the string you give to atoi(str) is correct.
I checked the binary file using hex editor, after inputting the number 1013.
int i = atoi("123");
std::ofstream file("filename", std::ios::bin);
file.write(reinterpret_cast<char*>(&i), sizeof(i));
Do not use pointers here.
Never use malloc / free in C++.
Use C++ file streams, not C streams.
Related
I am trying to retrieve some data from a binary file to put them in a linked list, here's my code to write to the file:
void Pila::memorizzafile()
{
int contatore = 0;
puntarec temp = puntatesta;
ofstream miofile;
miofile.open("data.dat" , ios::binary | ios::out);
if(!miofile) cerr << "errore";
else
{
while(temp)
{
temp->elem.writes(miofile);
contatore++;
temp = temp->next;
}
//I go back at the beginning of the file to write how many elements I have
miofile.seekp(0, ios::beg);
miofile.write((const char *)&contatore , sizeof(int));
miofile.close();
}
}
And the function writes:
void Fiche::writes(ofstream &miofile)
{
//Valore.
miofile.write((const char *)&Valore,sizeof(int));
//Materiale, I write the dimension of the string.
int buff = strlen(Materiale);
miofile.write((const char *)&buff,sizeof(int));
//Writing the string
miofile.write(Materiale,buff*sizeof(char));
//Dimension of Forma
buff = strlen(Forma);
miofile.write((const char*)&buff,sizeof(int));
//The string itself
miofile.write(Forma,buff*sizeof(char));
//Dimension of Colore.
buff = strlen(Colore);
miofile.write((const char*)&buff,sizeof(int));
//The string
miofile.write(Colore,buff*sizeof(char));
}
Now for the reading part, I am trying to make a constructor which should be able to read directly from the file, here it is:
Pila::Pila(char * nomefile)
{
puntatesta = 0;
int contatore = 0;
ifstream miofile;
miofile.open(nomefile , ios::binary | ios::in);
if(!miofile) cerr << "errore";
else
{
//I read how many records are stored in the file
miofile.read((char*)&contatore,sizeof(int));
Fish temp;
for(int i = 0; i < contatore; i++)
{
temp.reads(miofile);
push(temp);
}
miofile.close();
}
}
And the reading function:
void Fiche::reads(ifstream &miofile)
{
//I read the Valore
miofile.read((char*)&Valore,sizeof(int));
//I create a temporary char *
char * buffer;
int dim = 0;
//I read how long will be the string
miofile.read((char*)&dim,sizeof(int));
buffer = new char[dim];
miofile.read(buffer,dim);
//I use the set function I created to copy the buffer to the actual member char*
setMateriale(buffer);
delete [] buffer;
//Now it pretty much repeats itself for the other stuff
miofile.read((char*)&dim,sizeof(int));
buffer = new char[dim];
miofile.read(buffer,dim);
setForma(buffer);
delete [] buffer;
//And again.
miofile.read((char*)&dim,sizeof(int));
buffer = new char[dim];
miofile.read(buffer,dim);
setColore(buffer);
delete [] buffer;
}
The code doesn't give me any error, but on the screen I read random characters and not even remotely close to what I wrote on my file. Anyone could help me out, please?
EDIT:
As requested here's an example of input&output:
Fiche A("boh" , 4 , "no" , "gaia");
Fiche B("Marasco" , 3 , "boh" , "nonnt");
Fiche C("Valori" , 6 , "asd" , "hey");
Fiche D("TipO" , 7 , "lol" , "nonloso");
Pila pila;
pila.push(A);
pila.push(B);
pila.push(C);
pila.push(D);
pila.stampa();
pila.memorizzafile();
And:
Pila pila("data.dat");
pila.stampa();
This is probably your error:
//I go back at the beginning of the file to write how many elements I have
miofile.seekp(0, ios::beg);
miofile.write((const char *)&contatore , sizeof(int));
miofile.close();
By seeking to the beginning and then writing. You are overwriting part of the first object.
I think your best bet is to run through the list and count the elements first. Write this then proceed to write all the elements. It will probably be faster anyway (but you can time it to make sure).
I think you are using way to many C structures to hold things.
Also I would advice against a binary format unless you are saving huge amounts of information. A text format (for your data) is probably going to be just as good and will be human readable so you can look at the file and see what is wrong.
Im doing a small exercise to read a file which contains one long string and load this into an array of strings. So far I have:
char* data[11];
char buf[15];
int i = 0;
FILE* indata;
indata = fopen( "somefile.txt", "r" );
while( i < 11)
{
fgets(buf, 16, indata);
data[i] = buf;
i++;
}
fclose( indata );
somefile.txt: "aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbaahhhhhbbbbdddddddddddddbbbbb"
etc..
This reads in 15 characters, adds that string to the array and gets the next 15. The problem is the array always equals the last string, so if the last string is "ccccv" the whole array, data[0] = "ccccv", data[1] = "ccccv", data[2] = "ccccv" and so on.
Does anyone know why this is happening and whether there is a better way to do it? Thanks
Each pointer in data will point to the same memory area, which is buf.
You need to use strcpy + malloc.
Also is seems like you have a "minor" buffer overflow. buf is size 15 and you're reading 16 characters.
I'm trying to load an image file into a buffer in order to send it through a scket. The problem that I'm having is that the program creates a buffer with a valid size but it does not copy the whole file into the buffer. My code is as follow
//imgload.cpp
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
int main(int argc,char *argv){
FILE *f = NULL;
char filename[80];
char *buffer = NULL;
long file_bytes = 0;
char c = '\0';
int i = 0;
printf("-Enter a file to open:");
gets(filename);
f = fopen(filename,"rb");
if (f == NULL){
printf("\nError opening file.\n");
}else{
fseek(f,0,SEEK_END);
file_bytes = ftell(f);
fseek(f,0,SEEK_SET);
buffer = new char[file_bytes+10];
}
if (buffer != NULL){
printf("-%d + 10 bytes allocated\n",file_bytes);
}else{
printf("-Could not allocate memory\n");
// Call exit?.
}
while (c != EOF){
c = fgetc(f);
buffer[i] = c;
i++;
}
c = '\0';
buffer[i-1] = '\0'; // helps remove randome characters in buffer when copying is finished..
i = 0;
printf("buffer size is now: %d\n",strlen(buffer));
//release buffer to os and cleanup....
return 0;
}
> output
c:\Users\Desktop>imgload
-Enter a file to open:img.gif
-3491 + 10 bytes allocated
buffer size is now: 9
c:\Users\Desktop>imgload
-Enter a file to open:img2.gif
-1261 + 10 bytes allocated
buffer size is now: 7
From the output I can see that it's allocating the correct size for each image 3491 and 1261 bytes (i doubled checked the file sizes through windows and the sizes being allocated are correct) but the buffer sizes after supposedly copying is 9 and 7 bytes long. Why is it not copying the entire data?.
You are wrong. Image is binary data, nor string data. So there are two errors:
1) You can't check end of file with EOF constant. Because EOF is often defined as 0xFF and it is valid byte in binary file. So use feof() function to check for end of file. Or also you may check current position in file with maximal possible (you got it before with ftell()).
2) As file is binary it may contain \0 in middle. So you can't use string function to work with such data.
Also I see that you use C++ language. Tell me please why you use classical C syntax for file working? I think that using C++ features such as file streams, containers and iterators will simplify your program.
P.S. And I want to say that you program will have problems with really big files. Who knows maybe you will try to work with them. If 'yes', rewrite ftell/fseek functions to their int64 (long long int) equivalents. Also you'll need to fix array counter. Another good idea is to read file by blocks. Reading byte by byte is dramatically slower.
All this is unneeded and actually makes no sense:
c = '\0';
buffer[i-1] = '\0';
i = 0;
printf("buffer size is now: %d\n",strlen(buffer));
Don't use strlen for binary data. strlen stops at the first NUL (\0) byte. A binary file may contain many such bytes, so NUL can't be used.
-3491 + 10 bytes allocated /* There are 3491 bytes in the file. */
buffer size is now: 9 /* The first byte with the value 0. */
In conclusion, drop that part. You already have the size of the file.
You are reading a binary file like a text file. You can't check for EOF as this could be anywhere in the binary file.
I am having problem when i save a single variable of 460 elements in MATLAB using fwrite and when i try to read in MATLAB its fine but trying to access same bin file using fread in Visual C gives fine result for the first 88 values or so but then it experience EOF or so such as it doesn't give the required result for rest of elements. The code used for Visual C is given as under.
Though this question has been asked in the past post at some other forum as well but the answer doesnot solve the issue.
void main()
{
FILE *p;
long lsize;
float *temp;
int i;
size_t nn;
// Name of file
printf("Open File: r0.bin ");
p = fopen("r01.bin", "r");
// Determine the size of file
fseek (p, 0 , SEEK_END);
lsize = ftell (p);
rewind (p);
// Allocate memory
int a=sizeof(float);
lsize /= a;
temp = (float*) malloc (a*lsize);
// Reading the file
nn= fread(temp,a,lsize,p);
// printing the results
for (i=0;i<lsize;i+=4)
printf("\n %g %g %g %g",temp[i],temp[i+1],temp[i+2],temp[i+3] );
getch();
fclose(p);
}
Windows, right? Files are by default open in text mode, and byte 26 is interpreted as EOF marker. Rewrite your fopen as fopen("r01.bin", "rb") to force opening the file in binary mode.
Are you sure that MATLAB is outputting floats and not doubles? and this code is a bit unnecessary:
// get rid of these 2 statements
// int a=sizeof(float);
// lsize /= a;
temp = (float*) malloc( lsize );
// Reading the file
nn = fread( temp, 1, lsize, p );
I wanted to shrink the size of a large text file with float values into a binary .dat file, so I used (in c++):
// the text stream
std::ifstream fin(sourceFile);
// the binary output stream
std::ofstream out(destinationFile, std::ios::binary);
float val;
while(!fin.eof())
{
fin >> val;
out.write((char *)&val,sizeof(float));
}
fin.close();
out.close();
Then, I wanted to read all the float values from the rpeviously created binary file into a array of float values.
But when I try to read from this file I get an exception at the last line of code (the reading process):
// test read
std::ifstream fstream(destinationFile, std::ios::binary);
__int64 fileSize = 0;
struct __stat64 fileStat;
if(0 == _tstat64(destinationFile, &fileStat))
{
fileSize = fileStat.st_size;
}
//get the number of float tokens in the file
size_t tokensCount = fileSize / sizeof(float);
float* pBuff = new float[tokensCount];
fstream.read((char*)&pBuff, tokensCount * sizeof(float));
What am I doing wrong?
float* pBuff = new float[tokensCount];
fstream.read((char*)&pBuff, tokensCount * sizeof(float));
You are reading into the pBuff variable, not the buffer it points to. You mean:
fstream.read((char*)pBuff, tokensCount * sizeof(float));
Note that this:
while(!fin.eof())
{
fin >> val;
out.write((char *)&val,sizeof(float));
}
is not the correct way to read a file - it will read a garbage value at the end. You should almost never use the eof() function and you should ALWAYS check that a file read worked. Correct code is:
while( fin >> val )
{
out.write((char *)&val,sizeof(float));
}
Magnus' answer is correct and should solve your problem. I will only add that you wouldn't have had a problem in the first place if you had done as the gurus say and not used an evil C-style cast. If you change your last line to this:
fstream.read(static_cast<char*>(&pBuff), tokensCount * sizeof(float));
Then your program would have failed to compile and the error message would have led you to the solution.
EDIT: my solution does not work if pBuff is a pointer to any type other than char. So it's no use in the OP's case.