fread issues on windows 7 64 bits - c++

I'm trying to create a part in my program to write a binary file. It seems to work find but to be sure, I created an other part wich read this binary when I close the file.
Here come issues. I use the fopen/fwrite/fread functions and visual studio 12 with a Windows seven 64 bit and it seems that fread doesn't work correctly on Windows (I tried to read on linux, no problem and when I copy / paste the code, it compiles but the values I get are bad).
Here my code to read:
int en;
float fl;
double dl;
char c;
FILE *F;
int cpt;
cpt = 0;
if ((F = fopen("SimpleTest.twd", "rb")) == NULL)
{
printf("error on fopen\n");
return ;
}
while (cpt < 9)
{
fread(&fl, 4, 1, F);
printf("%f\n", fl);
cpt++;
}
I included cstdlib and cstdio and I'm sure of the existence of SimpleTest and the location of the file.
Thank

Related

C++ binary files not read correctly

I am reading a file that is written in high endian on a little endian intel processor in c++. The file is a generic file written in binary. I have tried reading it using open() and fopen() both but they both seem to get the same thing wrong. The file is a binary file for training images from the MNIST dataset. It contains 4 headers, each 32 bits in size and stored in high endian. My code is working, it is just not giving the right value for the 2nd header. It works for the rest of the headers. I even opened the file in a hex editor to see if the value might be wrong but it is right. The program, for some weird reason, reads only the value of the second header wrong:
Here is the code that deals with reading the headers only:
void DataHandler::readInputData(std::string path){
uint32_t headers[4];
char bytes[4];
std::ifstream file;
//I tried both open() and fopen() as seen below
file.open(path.c_str(), std::ios::binary | std::ios::in);
//FILE* f = fopen(path.c_str(), "rb");
if (file)
{
int i = 0;
while (i < 4)//4 headers
{
//if (fread(bytes, sizeof(bytes), 1, f))
//{
// headers[i] = format(bytes);
// ++i;
//}
file.read(bytes, sizeof(bytes));
headers[i++] = format(bytes);
}
printf("Done getting images file header.\n");
printf("magic: 0x%08x\n", headers[0]);
printf("nImages: 0x%08x\n", headers[1]);//THIS IS THE ONE THAT IS GETTING READ WRONG
printf("rows: 0x%08x\n", headers[2]);
printf("cols: 0x%08x\n", headers[3]);
exit(1);
//reading rest of the file code here
}
else
{
printf("Invalid Input File Path\n");
exit(1);
}
}
//converts high endian to little indian (required for Intel Processors)
uint32_t DataHandler::format(const char * bytes) const
{
return (uint32_t)((bytes[0] << 24) |
(bytes[1] << 16) |
(bytes[2] << 8) |
(bytes[3]));
}
Output I am getting is:
Done getting images file header.
magic: 0x00000803
nImages: 0xffffea60
rows: 0x0000001c
cols: 0x0000001c
nImages should be 60,000 or (0000ea60)h in hex but it is reading it as ffff... for some reason.
Here is the file opened in a hex editor:
As we can see, the 2nd 32 bit number is 0000ea60 but it is reading it wrong...
It seems that char is signed in your environment and therefore 0xEA in the data is sign-extended to 0xFFFFFFEA.
This will break the higher digits.
To prevent this, you should use unsigned char instead of char. (for both of element type of bytes and the argument of format())

`fwrite` doesn't work directly after `fread`?

I have a program which uses stdio for reading and writing a binary file. It caches the current stream position and will not seek if the read/write offset is already at the desired position.
However, an interesting problem appears, that when a byte is read and the following byte is written, it doesn't actually get written!
Here is a program to reproduce the problem:
#include <cstdio>
int main() {
FILE *f = fopen("test.bin", "wb");
unsigned char d[1024] = { 0 };
fwrite(d, 1, 1024, f);
fclose(f);
f = fopen("test.bin", "rb+");
for (size_t i = 0; i < 1024; i++) {
unsigned char a[1] = { 255 - (unsigned char)(i) };
fflush(f);
fwrite(a, 1, 1, f);
fflush(f);
fseek(f, i, SEEK_SET);
fread(a, 1, 1, f);
printf("%02X ", a[0]);
}
fclose(f);
return 0;
}
You are supposed to see it write the bytes FF down to 00, however only the first byte is written because it does not follow a fread immediately.
If it seeks before fwrite, it acts correctly.
The problem happens on Visual Studio 2010/2012 and TDM-GCC 4.7.1 (Windows), however it works on codepad which I guess is due to it being executed on Linux.
Any idea why this happens?
C99 §7.18.5.3/6 (quoted from N869 final draft):
“When a file is opened with update mode (’+’ as the second or third character in the
above list of mode argument values) […] input shall not be directly followed by output without an
intervening call to a file positioning function, unless the input operation encounters end-
of-file.”

Heap Corruption caused by Invalid Casting?

I have the code:
unsigned char *myArray = new unsigned char[40000];
char pixelInfo[3];
int c = 0;
while(!reader.eof()) //reader is a ifstream open to a BMP file
{
reader.read(pixelInfo, 3);
myArray[c] = (unsigned char)pixelInfo[0];
myArray[c + 1] = (unsigned char)pixelInfo[1];
myArray[c + 2] = (unsigned char)pixelInfo[2];
c += 3;
}
reader.close();
delete[] myArray; //I get HEAP CORRUPTION here
After some tests, I found it to be caused by the cast in the while loop, if I use a signed char myArray I don't get the error, but I must use unsigned char for the rest of my code.
Casting pixelInfo to unsigned char also gives the same error.
Is there any solution to this?
This is what you should do:
reader.read((char*)myArray, myArrayLength); /* note, that isn't (sizeof myArray) */
if (!reader) { /* report error */ }
If there's processing going on inside the loop, then
int c = 0;
while (c + 2 < myArraySize) //reader is a ifstream open to a BMP file
{
reader.read(pixelInfo, 3);
myArray[c] = (unsigned char)pixelInfo[0];
myArray[c + 1] = (unsigned char)pixelInfo[1];
myArray[c + 2] = (unsigned char)pixelInfo[2];
c += 3;
}
Trying to read after you've hit the end is not a problem -- you'll get junk in the rest of the array, but you can deal with that at the end.
Assuming your array is big enough to hold the whole file invites buffer corruption. Buffer overrun attacks involving image files with carefully crafted incorrect metadata are quite well-known.
in Mozilla
in Sun Java
in Internet Explorer
in Windows Media Player
again in Mozilla
in MSN Messenger
in Windows XP
Do not rely on the entire file content fitting in the calculated buffer size.
reader.eof() will only tell you if the previous read hit the end of the file, which causes your final iteration to write past the end of the array. What you want instead is to check if the current read hits the end of file. Change your while loop to:
while(reader.read(pixelInfo, 3)) //reader is a ifstream open to a BMP file
{
// ...
}
Note that you are reading 3 bytes at a time. If the total number of bytes is not divisible by 3 (not a multiple of 3) then only part of the pixelInfo array will actually be filled with correct data which may cause an error with your program. You could try the following piece of not tested code.
while(!reader.eof()) //reader is a ifstream open to a BMP file
{
reader.read(pixelInfo, 3);
for (int i = 0; i < reader.gcount(); i++) {
myArray[c+i] = pixelInfo[i];
}
c += 3;
}
Your code does follow the documentation on cplusplus.com very well since eof bit will be set after an incomplete read so this code will terminate after your last read however, as I mentioned before the likely cause of your issue is the fact that you are assigning likely junk data to the heap since pixelInfo[x] might not necessarily be set if 3 bytes were not read.

How to get the bytes of a file?

Simple question I know, what I want to do is be able to get the bytes of a file to use to add those bytes to an bit array, which I can then use to write to a file named bytes.exe and launch it. I know how to read the bytes of an existing file at runtime. But I don't know how to get the bytes of a file to copy and paste into my bitarray[] at design time.
The goal is to be able to write the bites of bitarray[] to myfile.exe at runtime, and then launch said file. There are many bitarray[]'s I'll be using, based on many different file types, so I'm looking for an easy method.
Is there some kind of decompiler that should be used? I just looked into resource scripts, but I don't want to attach any dependencies to my main .exe.
If you are targeting Windows, the easiest way to do this is to embed myfile.exe as a resource, then load the resource at runtime and create a file and write the contents of the resource to your new file.
If you can't use resources, then you'll need to create a source file (.c or .h) that initializes a byte array with the contents of myfile.exe and include that as part of your build. Check out this answer for one possible approach:
https://stackoverflow.com/a/73653/333127
EDIT: After further review, I don't think the source code in the link I referenced above will work for binary input files. Here's a quick alternative I just threw together:
#include <stdio.h>
#include <stdlib.h>
#define BYTES_PER_LINE 70
int main(int argc, char* argv[])
{
FILE* fp;
int ch;
int numBytes = 0;
if (argc < 2) {
printf("Usage: tobytes <file>\n");
exit(1);
}
fp = fopen(argv[1], "rb");
if (fp == NULL) {
printf("Cannot open file %s\n", argv[1]);
exit(1);
}
printf("char fileContents[] = {\n");
while ((ch = fgetc(fp)) != EOF) {
if (numBytes > 0)
printf(",");
++numBytes;
if (numBytes % BYTES_PER_LINE == 0)
printf("\n");
printf("0x%x", ch);
}
printf("\n};\n");
fclose(fp);
return 0;
}
It's not 100% clear what you want to do, but why not write a small program that reads a file and translates it into a C array.
That is if the file data is:
01 02 03 04 (binary)
The program will generate a file that is:
char data[] = {0x01, 0x02, 0x03, 0x04};
and then run this program as a prebuild step of your application (in your Makefile or whatever build system you are using), and generate the output into your source tree.
In that way the data would be compiled into your application and be available statically.
As I said, I'm not clear if this is the problem you are trying to solve.

fwrite and fread between matlab and c/cpp

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 );