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 );
Related
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!
I wrote a simple function to load a char * buffer from a file but when compiled through vs2017 it add rubbish at the end of the buffer but mingw compiled exe gives correct output
the function looks like something
#include <stdio.h>
#include <stdlib.h>
using namespace std;
char * loadfromfile(const char * _Filename)
{
char * buffer;
FILE * file = fopen(_Filename, "r");
if (!file)
return nullptr;
fseek(file, 0, SEEK_END);
auto _length = ftell(file);
buffer = new char[_length + 1];
rewind(file);
printf("characters read(loadformfile()) :%i\n",fread(buffer, sizeof(char), _length, file));
buffer[_length] = '\0';
fclose(file);
return buffer;
}
int main() {
char * str = loadfromfile("D:\\shutdown.bat");
printf("%s\n", (str) ? str : "failed to load");
delete[] str;
return 0;
}
VS2017 output:
characters read(loadformfile()) :86
#echo off
Set minutes=30
set /a seconds=%minutes%*60
TIMEOUT /T %seconds%
shutdown /s
\inst
g++ (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 7.1.0 output:
characters read(loadformfile()) :zu
#echo off
Set minutes=30
set /a seconds=%minutes%*60
TIMEOUT /T %seconds%
shutdown /s
file is:
#echo off
Set minutes=30
set /a seconds=%minutes%*60
TIMEOUT /T %seconds%
shutdown /s
EDIT:
A working solution
char * loadfromfile(const char * _Filename)
{
char * buffer;
FILE * file = fopen(_Filename, "r");
if (!file)
return nullptr;
fseek(file, 0, SEEK_END);
auto _length = ftell(file);
buffer = new char[_length + 1];
rewind(file);
buffer[fread(buffer, sizeof(char), _length, file)] = '\0';
fclose(file);
return buffer;
}
You can't portably use fseek()/ftell() to get the size of a file.
Per the C Standard, footnote 268, p 301:
Setting the file position indicator to end-of-file, as with
fseek(file, 0, SEEK_END), has undefined behavior for a binary
stream ...
and
7.21.9.2 The fseek function
... A binary stream need not meaningfully support fseek calls with a
whence value of SEEK_END.
So you can't reliably use fseek() to get to the end of a binary file. In fact, doing so is specifically stated by the C Standard to be undefined behavior.
OK, so you can use fseek() to get to the end of a file opened in text mode, but
7.21.9.4 The ftell function
...
For a text stream, its file position indicator contains unspecified
information, usable by the fseek function for returning the file
position indicator for the stream to its position at the time
of the ftell call; the difference between two such return
values is not necessarily a meaningful measure of the number of
characters written or read.
On a text file, ftell() doesn't return a value useful in getting the file size.
In short, using fseek()/ftell() to get the size of a file is fundamentally broken. The fact that it works sometimes is just an implementation detail.
I used fwrite to store some data and now I'm trying to use fread to read the data from the txt file for processing. I want to read the values individually but I can't figure out how you'd do that. This is what I have tried:
#include <stdio.h>
#include <stdlib.h>
int main ()
{
FILE * pFile;
long lSize;
unsigned short * buffer;
size_t result;
pFile = fopen ( "myfile.txt" , "rb" );
// obtain file size:
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
// allocate memory to contain the whole file:
buffer = (unsigned short *) malloc (sizeof(unsigned short)*lSize);
// copy the file into the buffer:
result = fread (buffer,1,lSize,pFile);
printf("%uz\n", result);
// terminate
fclose (pFile);
free (buffer);
return 0;
}
The above program compiles fine but when I run it with ./a.out I get a Segmentation fault. When I run it with sudo ./a.out I don't get seg fault but nothing prints out.
Any idea what I can do to fix it?
Problems I see:
Allocating more memory than needed
After
lSize = ftell (pFile);
lSize is set to the number of characters in the file, not the number of unsigned shorts. Hence, you need
buffer = malloc(lSize);
See Do I cast the result of malloc?. If you are using a C++ compiler (as your C++ tag seems to imply), you need to cast the return value of malloc.
Wrong format specifier
printf("%s\n", result);
uses the wrong format specifier to print result. You need to use
printf("%zu\n", result);
That line is the most likely culprit for the segmentation fault you are seeing.
Reading objects one by one
You can certainly use:
size_t count = lSize/sizeof(short);
for ( size_t i = 0; i < count; ++i )
{
unsigned short number;
result = fread (&number, sizeof(unsigned short), 1, pFile);
}
You can also use:
size_t count = lSize/sizeof(short);
for ( size_t i = 0; i < count; ++i )
{
result = fread (buffer+i, sizeof(unsigned short), 1, pFile);
}
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.
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.