Can some one explain me how to read content from a binary file?
I have done this:
FILE *fp;
int a[50];
fp=fopen("x.exe","rb");
while(fread(&a,sizeof(a),1,fp)==1)
{
printf("%d",a);
}
suppose that file only contain integer values.
Also I tired writing into a file using structures, and I can easily read&write contents of it, but when I try reading some other binary file I just got garbage value.
Or is it impossible to read a .exe file compliled and linked?
the correct way is:
int myreadfile(void)
{
FILE *fp;
int i, n;
unsigned char a[50];
if (!(fp=fopen("x.exe","rb"))) return(0);
while(n=fread(a,1,sizeof(a), fp))
{
for (i=0; i<n; i++)
printf("%02x ",a[i]);
printf("\n");
}
fclose(fp);
return 1;
}
Note that the buffer is of type unsigned char. That is because
a) you don't know if the file is a complete number of ints (but it is of char, i.e. bytes) and
b) in the printf call, the char will be converted to intand would the high bit of the char be a 1, it would be sign-extended, which we don't want.
Also, fread does not try to read a whole buffer but just any number of bytes still in the file (to a maximum of the buffer).
Related
I have a file in csv format look like this:
0.0060862,0.31869
0.025889,0.21183
0.064364,0.094135
0.10712,-0.0081176
0.15062,-0.073904
I would like to load the first column to array a and second column to array b. This is what the code looks like:
double a[5];
double b[5];
int i=0;
FILE* fileHandle = NULL;
fopen_s(&fileHandle, fileName.csv, "r+");
for(i=0;i<5;i++)
{
fscanf_s(fileHandle,"%lf,%lf",a[i],b[i]);
}
fclose(fileHandle);
Now I am converting the csv file to a binary file; the data is represented in 2's complement in unsigned int. How should I change my code?
I changed the code to
unsigned x[5];
unsigned y[5];
double a[5];
double b[5];
int i=0;
FILE* fileHandle = NULL;
fopen_s(&fileHandle, fileName.csv, "rb+");
for(i=0;i<5;i++)
{
fscanf_s(fileHandle,"%u,%u",x[i],y[i]);
a[i] = x[i]/(2^15);
b[i] = y[i]/(2^15);
}
fclose(fileHandle);
But x[i] and y[i] read from the binary is always 3435973836. How should I change my code to make it work?
When your data is binary, you don't need to convert it with fprintf and fscanf.
You can just read and write you array with fread and fwrite.
If your data alternates a and b records, you will better organize your variables the same way :
struct ab {
int a, b;
} ab[5];
and read it all in one shot with
fread(ab, sizeof (int), 10, fileHandle);
Then process it the way you like.
(see man fread, and man fwrite for details)
I'm getting some issues with reading the content of my array. I'm not sure if I'm storing it correctly as my result for every line is '1304056712'.
#include <stdio.h>
#include <stdlib.h>
#define INPUT "Input1.dat"
int main(int argc, char **argv) {
int data_index, char_index;
int file_data[1000];
FILE *file;
int line[5];
file = fopen(INPUT, "r");
if(file) {
data_index = 0;
while(fgets(line, sizeof line, file) != NULL) {
//printf("%s", line); ////// the line seems to be ok here
file_data[data_index++] = line;
}
fclose(file);
}
int j;
for(j = 0; j < data_index; j++) {
printf("%i\n", file_data[j]); // when i display data here, i get '1304056712'
}
return 0;
}
I think you need to say something like
file_data[data_index++] = atoi(line);
From your results I assume the file is a plain-text file.
You cannot simply read the line from file (a string, an array of characters) into an array of integers, this will not work. When using pointers (as you do by passing line to fgets()) to write data, there will be no conversion done. Instead, you should read the line into an array of chars and then convert it to integers using either sscanf(), atoi() or some other function of your choice.
fgets reads newline terminated strings. If you're reading binary data, you need fread. If you're reading text, you should declare line as an array of char big enough for the longest line in the file.
Because file_data is an array of char, file_data[data_index] is a single character. It is being assigned a pointer (the base address of int line[5] buffer). If reading binary data, file_data should be an array of integers. If reading strings, it should be an array of string, ie char pointers, like char * file_data[1000]
you also need to initialize data_index=0 outside the if (file) ... block, because the output loop needs it to be set even if the file failed to open. And when looping and storing input, the loop should test that it's not reached the size of the array being stored into.
I want to read the 4 first bytes from a binnary file which is a song.wav type. In a .wav file the 4 first bytes must be 52-46-49-49 and I have to read them to check later if they are true.
The thing is that I have a compile arror at the fread line which says invalid conversion from "unsigned char" to "void" and initialzing argument 1 of 'size_t fread(void*,size_t,size_t,FILE*) and i dont know what it means.
I saw in a previous topic tha this is the way that fread must be done if i want to read byte by byte. If anyone has any idea of how i can read byte by byte and store them in an array that be great. Thank you.
void checksong(char *argv[]){
FILE *myfile;
int i;
unsigned char k[4];
myfile=fopen(argv[2],"r");
i=0;
for(i=0; i<4; i++){
fread(k[i],1,1,myfile);
}
for(i=0; i<4; i++){
printf("%c\n", k[i]);
}
return ;
}
It is a single error:
Invalid conversion from unsigned charto void* initializing argument 1 of
size_t fread(void*,size_t,size_t,FILE*)
It means k[i] is an unsigned char, and not a pointer. You should use &k[i] or k+i.
However, you don't really need to read byte by byte. You can read 4 bytes, no loops involved:
fread(k, 4, 1, myfile);
Printing the numbers:
for (i=0; i<4; i++)
printf("%d\n", k[i]);
In order to read exactly one byte and store it into k at index i, you need to provide the address of element i
for(i=0; i<4; i++){
fread(&k[i],1,1,myfile);
}
However, you'd rather read the whole 4 bytes in one go if you're interested in them 4. So no for loop at all, and just do:
fread(k,1,4,myfile);
It is also good practice to test the return code of fread (and any I/O operation for that matter) in case it fails. man fread for more information.
You can use just
char buffer[4];
fread(buffer,1,4,myfile);
you need not to use fread() Even the fgetc() works well. Simple coding. SImple as reading a text file.
#include <stdio.h>
int main(int argc, char** argv)
{
FILE* f = fopen("lak", "rb");
fseek(f,0,SEEK_END);
long lsize=0,i=0;
lsize = ftell(f);
rewind(f);
while(i<lsize){
int first = fgetc(f);
i++;
printf("first byte = %x\n", (unsigned)first); //you can do anything with
//first now
}
fclose(f);
return 0;
}
Im having some trouble figuring out how to properly format fread statements. The below code is just some randomn stuff Im practicing with. Basically it fills information into the first array (s), writes 's' to a file, and then reads the file into the second array (s2). However I can't seem to get the fread statement formated in a way that doesnt give an error or return garbage. The arrays are in char datatype because, if my understanding is correct, char uses less memory than other datatypes. The eventual application of this practice code is for a data compression project.
#include<stdio.h>
#include<string.h>
FILE *fp;
//file pointer
char s[56];
//first string
char s2[56];
//target string for the fread
int n=0;
//counting variable
int m=0;
int main (void)
{
fp=fopen("test.bin", "w+");
//open a file for reading and writing
strcpy(s, "101010001101010");
//input for the string
for(n=0;n<56;n++)
{
if(s[n]==1)
m=n;
else if(s[n]==0)
m=n;
}
printf("%d\n", m);
//the above for loop finds how many elements in 's' are filled with 1's and 0's
for(n=0;n<m;n++)
{
printf("%c", s[n]);
}
//for loop to print 's'
fwrite(s, m, 1, fp);
//writes 's' to the first file
s2=fread(&s2, m, 1, fp);
//an attempt to use fread...
printf("\n\ns2\n\n");
for(n=0;n<m;n++)
{
printf("%c", s2[n]);
}
printf("\n");
//for loop to print 's2'
fclose(fp);
printf("\n\n");
printf("press any number to close program\n");
scanf("%d", &m);
}
A FILE structure has an implicit seek position within the file. You read and write from that seek position. If you want to read what you have written, you need to change the seek position back to the beginning of the file with a call to fseek(). In fact, for a file open for reading and writing, you must call fseek() when switching between reading and writing.
The return value of the fread function is of type size_t. It is the number of elements successfully read. (reference: http://www.cplusplus.com/reference/cstdio/fread/)
Don't assign it to s2. Simply use fread(&s2, m, 1, fp);
I am trying to solve a problem which requires me to read a file and generate another file which has the same contents as the original but every fourth byte removed.I tried it doing this way ...
int main()
{
FILE *p;
FILE *q;
int i=0,k=0;
char c;
p = fopen("C:\\Users\\Teja\\Desktop\\Beethoven.raw","rw");
q = fopen("C:\\Users\\Teja\\Desktop\\Beethoven_new.raw","w+");
printf("%x is the EOF character \n",EOF);
while((c=fgetc(p))!=EOF)
{
if(i==3){
i=0;
printf("Removing %x %d \n",c,k++);
}
else{
printf("Putting %x %d \n",c,k++);
fputc(c,q);
i++;
}
}
fclose(p);
fclose(q);
return 0;
}
The file that i was trying to read is a .raw file and it is around 10-15 MB. I notice that the above code stops reading the file after typically 88 bytes. Is there any way to read large files or am i doing anything wrong ?
In addition to what has already been pointed out, a note on opening files: It sounds like your file in a binary file, which means you must add a b to the mode string. Additionally, rw is not a mode, since you only read from p you want rb, and since you only write to q you want wb or wb+.
By the way, the reason why you need fgetc to return an int is because fgetc must return 257 unique values: all the possible values of char, that is 0x00 thru 0xFF as well as something unique to signify EOF, usually -1
Change
char c;
to
int c;
as the return type of fetgetc() is an int and not char.