fread to C++ Vecotor - c++

I have a binary file,
FILE *fp;
fp = fopen("file_name.data", "rb");
Which can be successfully read using fread() with the following C code
int S = 8;
int *table = (int*)malloc(S*sizeof(int));
fread(table, S*sizeof(int), 1, fp);
But when I read file to C++ vector, the result is wrong
vector<int> table;
table.resize(S);
fread(&table[0],table.size(), 1, fp);
Is there anything wrong with above code ?.

table.size() returns the number of elements in the std::vector, not the number of bytes. You still need to multiply that by the size of each element, just like you do in the C code.
fread(&table[0],table.size()*sizeof(int), 1, fp);

Your fread should be:-
fread (&table[0], sizeof(vector<int>::value_type), table.size(), fp);
// OR
fread (&table[0], sizeof(int), table.size(), fp);

Both appear to be wrong (although the C version looks like it will work).
See: http://www.tutorialspoint.com/c_standard_library/c_function_fread.htm
Try these:
int S = 8;
int *table = (int*)malloc(S*sizeof(int));
fread(table, sizeof(int), S, fp);
vector<int> table;
table.resize(S);
fread(&table[0], sizeof(int), table.size(), fp);

Related

C++ fread() reports back right size read, but buffer is missing data on Windows

Scenario: I have a file that is 8,203,685 bytes long in binary, and I am using fread() to read in the file.
Problem: Hexdumping the data after the fread() on both Linux and Windows yields different results. Both hexdump files are the same size, but on Linux it matches the original input file that went in, whereas on Windows starting at byte 8,200,193 the rest of the hexdump contains 0's.
Code:
int main(void)
{
FILE * fp = fopen("input.exe", "rb");
unsigned char * data = NULL;
long size = 0;
if (fp)
{
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
data = (unsigned char *)malloc(size);
size_t read_bytes = fread(data, 1, size, fp);
// print out read_bytes, value is equal to size
// Hex dump using ofstream. Hexdump file is different here on Windows vs
// on Linux. Last ~3000 bytes are all 0's on Windows.
std::ofstream out("hexdump.bin", std::ios::binary | std::ios::trunc);
out.write(reinterpret_cast<char *>(data), size);
out.close();
FILE * out_file = fopen("hexdump_with_FILE.bin", "wb");
fwrite(data, 1, size, out_file);
fflush(out_file);
fclose(out_file);
}
if (fp) fclose(fp);
if (data) free(data);
return 0;
}
Has anyone seen this behavior before, or have an idea of what might be causing the behavior that I am seeing?
P.S. Everything works as expected when using ifstream and its read function
Thanks!

How to pass binary data from C++ to Node.js

I have a binary data in c++ variable buffer as below:
int len = 39767;
uint16_t * buffer = (uint16_t) malloc(len);
FILE * fp = fopen("rahul.jpg", "rb"); // size of file is 39767 byte.
fread(buffer, len, 1, fp);
fclose(fp);
fp = fopen("rahul3.jpg", "wb");
fwrite(buffer, len, 1, fp); // Here it is written correct.
fclose(fp);
I want to pass this buffer to Node.js and write to a file. I used below line to convert it to Local and then wrapping to an Object:
Local<String> str = Nan::New(buffer).ToLocalChecked();
return scope.Escape(str);
But, in node.js when I am checking length of received data it prints 9 only and value seems corrupted.
console.log(data);
console.log("len = " + data.length );
fs.writeFileSync('rahul2.jpg', data, 'binary');
Here rahul2.jpg is corrupted and is of 9 bytes only. How can we get rahul2.jpg from node.js code same as rahul.jpg in c++? Which Nan::New() we should use to pass binary data unaffected? Please help. Thanks.
Try something like this:
Local<Value> returnValue = Nan::CopyBuffer(buffer, len).ToLocalChecked();
and, by the way, fread returns the number of bytes read from file, so it is better to do as follows:
int truelen = fread(buffer, len, 1, fp);
. . .
fwrite(buffer, truelen, 1, fp);
Local<String> str = Nan::NewOneByteString((uint8_t *) buffer, len).ToLocalChecked();
I used above code in C++ which solved the issue. In node.js used the below code to write to file:
fs.writeFileSync('rahul2.jpg', data, 'binary');
Thanks.

Having issues with fread and fwrite when writing some characters and a struct to a file and reading them back

I want to write three characters to a file, then a struct, then one more character.
Finally I would like to read the character before the struct, the struct itself, the character after the struct and display them on the screen.
struct stuff{
int a;
int b;
};
int main(){
FILE * fp = fopen("input.txt", "w+");
char charA = 'z';
char charB = 's';
char charC = 'q';
char charD = 'e';
//create a struct of type stuff
stuff s;
s.a = 123;
s.b = 2111;
//fwrite three first chars
fwrite(&charA, 1, sizeof(char), fp);
fwrite(&charB, 1, sizeof(char), fp);
fwrite(&charC, 1, sizeof(char), fp);
//fwrite the struct
fwrite(&s, 1, sizeof(struct stuff), fp);
//fwrite the last char
fwrite(&charD, 1, sizeof(char), fp);
//read the char before the struct, the struct itself,
// and the char after the struct
char expectedCharC;
stuff expectedStructS;
char expectedCharD;
fseek(fp, sizeof(struct stuff) + sizeof(char), SEEK_END);
fread(&expectedCharC, 1, sizeof(char), fp);
fread(&expectedStructS, 1, sizeof(struct stuff), fp);
fseek(fp, sizeof(char)*3 + sizeof(struct stuff), SEEK_SET);
fread(&expectedCharD, 1, sizeof(char), fp);
cout<<expectedCharC<<" "<<expectedStructS.a<<" ";
cout<<expectedStructS.b<<" "<<expectedCharD<<endl;
fclose(fp);
return 0;
}
Instead of this result:
q 123 2111 e
I get this result:
4197174 0 e
I don't know what I'm doing wrong. I'm writing bytes to the file, reading them back and displaying them on the screen. What goes wrong?
thank you in advance
Wow, lots of problems in your code. Let's tackle them one by one.
As mentioned by unwind, the mode you're using to open the file seems to be incorrect as to what you're trying to do. For one, you're trying to read from a file that is opened for write-only.
You're using fwrite wrongly. It goes fwrite(pointer to data, size of each data, number of data, FILE pointer);.
You're using fseek wrongly. I see you're confused with the offset parameter. This offset defines a signed distance from the origin specified as the last argument to fseek. Therefore, if you're at SEEK_END, you should be moving backwards by having your offset be a negative number.
I've done these changes myself and now it works. Output: q 123 2111 e
Here's a nice little website for you too. Helped me with your problem.
Thank you for reading.
First, as has been pointed out, you must open the file in binary
mode. Even then, just dumping the bytes of a struct means
that you won't be able to read it correctly some time in the
future. But as long as you're reading from the same process, it
should be OK.
The real problem is what you are doing with all of the fseek:
before the first fread, you do an fseek beyond the end of
the file. Any read from that position is guaranteed to fail.
You really should check the status of the file, and ensure that
the fread has succeeded before accessing any of the values you
read. If it failed, accessing the variables (at least those in
stuff) is undefined behavior; most likely, you'll get some
random garbage.
Your first fseek should probably be to the beginning of the file, or
else:
fseek( fp, -(sizeof( stuff ) + 4), SEEK_BEG);
If you've just read the struct, then the second fseek is
unnecessary as well. (In your case, it means that the final
'e' is correctly read.)
You must open your file in binary mode for this to work.
FILE * fp = fopen("input.txt", "wb+");
^
|
blam!
Your wanted result is also a bit unclear, shouldn't it start with the three characters 'z', 's' and 'q', and then have the integers? Note that the integers are likely to appear byte-swapped if you're on a little-endian machine.
To help debug the code, you should add return-value checking to all I/O calls, since I/O can fail. Also note that sizeof (char) is always 1, so it's not very beneficial to write it like that.

Unable to write using fwrite()

I'm using fwrite in an MFC application to print content of lBuffer as shown in following C++ code:
PvBuffer *lBuffer = NULL;
// Retrieve next buffer
PvResult lResult = lStream.RetrieveBuffer(&lBuffer, &lOperationResult, 1000);
if (lResult.IsOK())
{
FILE *fp = fopen("C:\\Users\\acm45\\Desktop\\abuffer.bin", "wb");
fwrite(lBuffer, 1, 10075968, fp);
fclose(fp);
}
Any idea why the content of the file abuffer.bin is always empty even though IResult returns success?
Note the file is always created when I run the program, but it is empty and size is 0KB.
Update:
To debug I did this:
FILE *fp = fopen("C:\\Users\\acm45\\Desktop\\abuffer.bin", "wb");
if (fp) {
fwrite(lBuffer, 1,10075968, fp);
fclose(fp);
} else {
printf("error opening file");
}
and the output did not print "error opening file", but still the file is empty. What do I do now?
I guess you are having some undefined behaviour there.
The man page of fwrite says:
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
The function fwrite() writes nmemb elements of data, each size bytes long, to the stream pointed to by stream, obtaining them from the location given by ptr.
But your call
lStream.RetrieveBuffer( &lBuffer, &lOperationResult, 1000 );
lets me guess you don't have 10075968 elements with each one byte long.
Also: Is your buffer a collection of POD elements? If not, that's another reason for undefined behaviour. fwrite is only for POD types.
Generally, it is better to use C++ streams.
addendum to explain fwrite
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
Here, size means the size of a single element.
nmemb is the number of such elements. For example:
...
struct Foobar {
int frob;
};
int main () {
...
Foobar thingies[5];
fwrite (thingies, sizeof(Foobar), 5, some_file);
}
A more generic approach is this:
Foobar thingies[5];
const size_t nm = sizeof(thingies) / sizeof(Foobar);
fwrite (thingies, sizeof(Foobar), nm, some_file);
This read: "size of the array, divided by size of a single element, which equals the number of elements in that array".
But note that this only works for arrays, not pointers!
Foobar *thingies = new Foobar[5];
const size_t nm = sizeof(thingies) / sizeof(Foobar);
fwrite (thingies, sizeof(Foobar), nm, some_file);
// THIS IS WRONG. sizeof(thingies) now equals to the
// size of a pointer!
Try doing this:
FILE *fp = fopen("C:\\Users\\acm45\\Desktop\\abuffer.bin", "wb");
if (fp) {
fwrite(lBuffer, 1, 10075968, fp);
fclose(fp);
} else {
perror("fopen");
}
Check whether you are retrieving the buffer correctly. Use the function if available in that class to get the size of the buffer and pass it instead of that constant.

Need to read data from png file and save it to the new one, how? C++

I try to read data from one PNG file, and want to write this data to the new file and save it.
I do such stuff like that:
FILE *fp = fopen("C:\\dev\\1.png", "rb");
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
rewind(fp);
char *buffer = (char*)malloc(sizeof(char)*size);
size_t result = fread(buffer, 1, size, fp);
FILE *tmpf = fopen("C:\\dev\\1_1.png", "wb");
fputs(buffer, tmpf);
fflush(tmpf);
fclose(tmpf);
I've got problem, that second file only has in its content, only that: ‰PNG SUB
In debugging , I have checked, long size = 652521, and size_t result has got the same size...
Don't understand, why I can't write all data to the second file...
Don't use fputs - use fwrite - fputs is for strings and will terminate on the first zero byte.
Change:
fputs(buffer, tmpf);
to:
fwrite(buffer, 1, size, tmpf);