I am not able to understand the fread fwrite behavior of the following code snippet, exemplified by the code is straightforward:
#include <stdio.h>
int main(void)
{
FILE *fp;
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int temp[100] = {0};
int i;
fp = fopen("testdata.bin","wb");
if( fp!= NULL ) {
fwrite( arr,sizeof(int), 10, fp);
fclose(fp);
}
fp = fopen("testdata.bin","rb");
if( fp!= NULL ) {
fread( temp,sizeof(int), 10, fp);
fclose(fp);
}
for(i=0;i<100;i++)
printf("%#x,",temp[i]);
printf("\b \n");
return 0;
}
The output on stdout is:
0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
which makes sense. However, when I open the testdata.bin file, I see only two bytes for value (int) where I expect 4 bytes as size of int is 4 on my machine.
Here is the content of testdata.bin:
0x00000001: 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00
0x00000010: 09 00 0a 00
I would have expected
0x00000001: 01 00 00 00 02 00 00 00 03 00 00 00 ...
Any ideas?
I think fwrite is working fine. Change the declaration of temp so the type is an array of one-byte unsigned characters:
unsigned char temp [100] = {0} ;
The current version of the code displays a four-byte integer each time in the print statement. This will confirm that the contents of the file are as you expect. On my machine:
0x1,0,0,0,0x2,0,0,0,0x3,0,0,0,0x4,0,0,0,0x5,0,0,0,0x6,0,0,0,0x7,0,0,0,0x8,0,0,0,0x9,0,0,0,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Related
I'm having an issue with (I think) memory reallocation in C. The program is meant to run such that when fopen(array, &num); is called, it will first retrieve the number of elements in the array from file and place that in num, reallocate memory for the array pointer given to give it enough room to store the contents of the file proper, then copy the values over into that array. This seems to work while still in the fopen function (shown by 'mark 1'), but does not work outside of this (shown by 'mark 2') instead seeming to spew out random memory garbage. Any help appreciated (both with code and formatting my poorly laid out question).
//main.c
void Rtest(){
char num;
struct individual *array;
array = (struct individual *) malloc(sizeof(struct individual));
openf(array, &num);
printf("%d\n", num);
for (int i = 0; i < num; i++) {printf("%s\n", array[i].name);} //mark 2
free(array);
}
//fil.h
struct individual {
char name[32];
char stats[7];
char role;
char roles[13];
};
void openf(struct individual *array, char *num){
FILE *fp;
fp = fopen("save.bin", "rb");
fread(num, 1, sizeof(char), fp);
array = (struct individual *)realloc(array, *num * sizeof(struct individual));
printf("%d\n", sizeof(*array));
fread(array, *num, sizeof(struct individual), fp);
for (int i = 0; i < *num; i++) {printf("%s\n", array[i].name);} //mark 1
fclose(fp);
}
File contents:
03 43 61 72 6C 73 6F 6E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 03 04 05 06 08 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 43 61 72 6C 73 6F 6E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 03 04 05 06 08 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 43 61 72 6C 73 6F 6E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 03 04 05 06 08 00 01 02 03 04 05 06 07 08 09 0A 0B 0C
When you want to change the argument inside a function, you pass a pointer to it.
For example, inside Rtest you declared a char called num. It has no value, and you sent it to openf, But you actually sent the pointer to num since you wanted to change its value, you did it correctly and indeed openf changed num value successfully.
But how about array? Well, you declared it on Rtest and allocated space in memory for it, which is all correct. Then, you wanted to send it to Rtest as a pointer so the function could change it.
array is a variable of the type "pointer to struct individual". This is okay, but if you wanted to change it inside Rtest, well you need to send a pointer for that variables.. hence, you needed a "POINTER TO pointer to struct individual". Note that the variable name was copied from before and I just added "POINTER TO"
I'm sure you know what pointer to pointer is, and what you needed to do is use:
openf(&array, &num);
And of course modift openf as well so it will use the new "pointer to pointer", something like that:
void openf(struct individual **array, char *num){
FILE *fp;
fp = fopen("save.bin", "rb");
fread(num, 1, sizeof(char), fp);
*array = (struct individual **)realloc(*array, *num * sizeof(struct individual));
printf("%d\n", sizeof(**array));
fread(*array, *num, sizeof(struct individual), fp);
for (int i = 0; i < *num; i++) {printf("%s\n", (*array)[i].name);} //mark 1
fclose(fp);
}
When I run this code on my machine, along with Rtest and provided save.bin I get the following output:
53
Carlson
Carlson
Carlson
3
Carlson
Carlson
Carlson
EDIT:
As #WhozCraig mentioned in the comments, You could use the unused return value for the function and return the pointer for the "new" array, which might be a slightly better way of doing things here instead of the "pointer to pointer" stuff, but its up to you.
This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 3 years ago.
I am trying to load a 2D array created by numpy and read the elements in C, but I get Segmentation fault(core dumped ) error while running it. The code goes by the lines of
#include <stdio.h>
#include <string.h>
int main(){
char *file;
FILE *input;
int N1, N2, ii, jj;
float element;
strcpy(file, "/home/caesar/Desktop/test.bin");
input = fopen(file, "rb");
fread(&N1, sizeof(int), 1, input);
fread(&N2, sizeof(int), 1, input);
float memoryarray[N1][N2];
for(ii= 0; ii<N1; ii++){
for(jj=0; jj<N2; jj++){
fread(&element, sizeof(float), 1, input);
memoryarray[ii][jj]= element;
}
}
printf("%f", memoryarray[2][3]);
fclose(input);
return 0;
}
This is the starting for a task where I will have to read elements from matrices of the form 400*400*400 or so. The idea is to read all elements from the file and store it in memory and then read from memory index wise when necessary, for example, here i am trying to access and print the element in the second row third column.
P.S: I am quite new to pointers.
Dear all, I tried the methods you said., here is the modified version of the code, the segmentation fault error is gone but the output is either all zeros, or is just plain garbage values.
I ran the executable three times and the outputs I got were
Output1: -0.000000
Output 2: 0.000000
Output 3 : -97341413674450944.000000
My array contains integers btw
Here is the modified version of the code
#include <stdio.h>
#include <string.h>
void main(){
const char file[] ="/home/caesar/Desktop/test.bin";
FILE *input;
int N1, N2, ii, jj;
float element;
//strcpy(file, "/home/caesar/Desktop/test.bin");
input = fopen(file, "r");
fread(&N1, sizeof(int), 1, input);
fread(&N2, sizeof(int), 1, input);
float memoryarray[N1][N2];
for(ii= 0; ii<N1; ii++){
for(jj=0; jj<N2; jj++){
fread(&element, sizeof(float), 1, input);
memoryarray[ii][jj]= element;
}
}
printf("%f", memoryarray[1][2]);
fclose(input);
Also here is the hex dump of the file that i am trying to open. Some of you asked me to verify whether fopen() is working or not, i checked, it is working.
00000000 00 00 40 40 00 00 40 40 01 00 00 00 00 00 00 00 |..##..##........|
00000010 02 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 |................|
*
00000030 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................|
00000040 05 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 |................|
00000050
So here is my problem in brief. I have multidimensional arrays of double precision floats written to a file using python. I want to take those files and access the elements whenever necessary by using the index of the elements to get the values. Any C code to do so would solve my problem.
Here is the python code i am using to write the file
with open('/home/caesar/Desktop/test.bin', 'wb') as myfile:
N= np.zeros(2, dtype= np.float32, order= "C")
N[0]= 3
N[1]= 3
a= [[1,2,3],[2,3,4], [4,5,6]]
N.astype(np.float32).tofile(myfile)
b= np.asarray(a)
b.tofile(myfile)
strcpy(file, "/home/caesar/Desktop/test.bin");
This writes to a garbage memory address.
You should either declare file as an array of suitable size, like this:
char file[100];
or
initialize the char pointer directly with the path like this (and get rid of the strcpy):
const char *file = "/home/caesar/Desktop/test.bin";
or the best, as per common consensus (refer comments):
fopen("/home/caesar/Desktop/test.bin", "rb");
I'm trying to read UTF file and decided to read it in binary mode and skip non-ASCII as file consists of valid english text basically. I'm stuck at fread returning 1 instead of number of bytes requested. First output of print_hex IMHO shows it has read more than 1 char. I've read some examples of reading binary files in C e.g Read and write to binary files in C?, read about fread e.g. here https://en.cppreference.com/w/c/io/fread and here How does fread really work?, still puzzled why it returns 1. File hexdump, and complete C code and output below.
ADD: compiled by gcc, run on Linux.
File:
00000000 ff fe 41 00 41 00 42 00 61 00 0d 00 0a 00 41 00 |..A.A.B.a.....A.|
00000010 41 00 45 00 72 00 0d 00 0a 00 66 00 73 00 61 00 |A.E.r.....f.s.a.|
00000020 6a 00 0d 00 0a 00 64 00 73 00 61 00 66 00 64 00 |j.....d.s.a.f.d.|
00000030 73 00 61 00 66 00 64 00 73 00 61 00 0d 00 0a 00 |s.a.f.d.s.a.....|
00000040 64 00 66 00 73 00 61 00 0d 00 0a 00 66 00 64 00 |d.f.s.a.....f.d.|
00000050 73 00 61 00 66 00 73 00 64 00 61 00 66 00 0d 00 |s.a.f.s.d.a.f...|
00000060 0a 00 0d 00 0a 00 0d 00 0a 00 |..........|
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_hex(const char *s)
{
while(*s)
printf("%02x ", (unsigned char) *s++);
printf("\n");
}
int main(){
#define files_qty 5
const char* files_array[][2]={{"xx","a"},{"zz","b"},{"xxx","d"},{"d","sd"},{"as","sd"}};
const char* file_postfix = ".txt";
char* file_out_name = "XXX_AD.txt";
FILE* file_out = fopen (file_out_name, "w");
printf ("This app reads txt files with hardcoded names and writes to file %s\n",file_out_name);
/* ssize_t bytes_read = 1; //signed size_t */
size_t n_bytes = 10;
unsigned char* string_in;
char* string_out;
char* file_name;
string_in = (char*) malloc (n_bytes+1);
string_out = (char*) malloc (n_bytes+50);
file_name = (char*) malloc (n_bytes+1); /* more error prone would be to loop through array for max file name length */
int i;
size_t n;
for (i=0;i<files_qty;i++)
{
strcpy (file_name,files_array[i][0]);
FILE* file = fopen (strcat(file_name,file_postfix), "rb");
if (file!= NULL)
{
int k=0;
while (n=fread (string_in, sizeof(char), n_bytes, file)>0)
{
printf("bytes read:%lu\n",(unsigned long) n);
print_hex(string_in);
int j;
for (j=0;j<n;j++)
{
switch (string_in[j])
{
case 0x00:
case 0xff:
case 0xfe:
case 0x0a:
break;
case 0x0d:
string_out[k]=0x00;
fprintf (file_out, "%s;%s;%s\n", files_array[i][0], files_array[i][1], string_out);
k=0;
printf("out:\n");
print_hex(string_out);
break;
default:
string_out[k++]=string_in[j];
}
}
}
fclose (file);
}
else
{
perror (file_name); /* why didn't the file open? */
}
}
free (string_in);
free (string_out);
free (file_name);
return 0;
}
Output:
bytes read:1
ff fe 41
bytes read:1
0d
out:
bytes read:1
72
bytes read:1
61
bytes read:1
73
bytes read:1
61
bytes read:1
0d
out:
72 61 73 61
bytes read:1
61
bytes read:1
73
bytes read:1
61
bytes read:1
0a
You have a precedence problem. Simple assignment has lower precedence than comparison. So the following line:
while(n=fread (string_in, sizeof(char), n_bytes, file)>0)
is evaluated as (extra parenthesis)
while (n=(fread (string_in, sizeof(char), n_bytes, file)>0))
Therefore n is being assigned as 1 because fread is returning a value > 0
Instead, explicitly add parenthesis as:
while((n=fread (string_in, sizeof(char), n_bytes, file))>0)
I made a function in C to create a file using Unix command dd:
dd if=/dev/zero of=file.data bs=8 count=32
This works and created file.data with size 256 bytes and if I open the file I can see it's empty.
Now I want to write to a specific position in this file using fseek and fwrite, but whenever I try to write to a position different from 0, it does nothing.
For example, If I want to write to position 2, I must also write to position 0 and 1.
void createFile() {
char command[100];
sprintf(comando, "dd if=/dev/zero of=file.data bs=8 count=32");
system(command);
}
void writeFile(int position, char * data) {
FILE * file = fopen("file.data", "r+");
fseek(file, position, SEEK_SET);
fwrite(data, strlen(data), 1, file);
fclose(file);
}
Some examples
Input:
writeFile(0, "0");
writeFile(1, "1");
writeFile(2, "2");
output > 012
Input:
writeFile(2, "2");
writeFile(1, "1");
writeFile(0, "0");
output > 012
Input:
writeFile(1, "1");
writeFile(2, "2");
output > empty
Is there some way to write into the file without having to write into the previous positions also?
You don't have to do anything special. Your code works, as long as you know how to demonstrate that it works. Here's a mildly extended version of it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void createFile(void)
{
char command[100];
sprintf(command, "dd if=/dev/zero of=file.data bs=8 count=32"); // Typo fixed!
system(command);
}
static void writeFile(int position, char *data)
{
FILE *file = fopen("file.data", "r+");
fseek(file, position, SEEK_SET);
fwrite(data, strlen(data), 1, file);
fclose(file);
}
int main(void)
{
createFile();
system("odx file.data");
writeFile(2, "012");
system("odx file.data");
return 0;
}
The odx command is a hex dump program; you could use od -c or xxd -g1 instead.
The sample output is:
32+0 records in
32+0 records out
256 bytes transferred in 0.000109 secs (2349544 bytes/sec)
0x0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
* (15)
0x0100:
0x0000: 00 00 30 31 32 00 00 00 00 00 00 00 00 00 00 00 ..012...........
0x0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
* (14)
0x0100:
The first three lines are from dd. I'm not convinced that using dd is necessary, but it does no great harm. The next three lines indicate that the first 16 bytes in the file are all zero bytes, and that this pattern repeats for 15 more lines, and then you reach EOF at offset 0x100 (25610). The next four lines show that there are 2 null bytes, then the three digits 012, then all null bytes to the end of file.
I have this strange problem:
I write 16 chars to a binary file and then I write 3 integers but when I open my file with some binary file viewer, I see an extra byte is added (which equals 0x0D).
Here's my code:
for(i = 0; i < 16; i++)
{
if(i < strlen(inputStr))
{
myCharBuf[0] = inputStr[i];
}
else
{
myCharBuf[0] = 0;
}
fwrite(myCharBuf, sizeof(char), 1, myFile);
}
myIntBuf[0] = inputNumber1;
fwrite(myIntBuf, sizeof(int), 1 ,myFile);
myIntBuf[0] = inputNumber2;
fwrite(myIntBuf, sizeof(int), 1 ,myFile);
myIntBuf[0] = inputNumber3;
fwrite(myIntBuf, sizeof(int), 1 ,myFile);
I get the following byte-values:
61 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0D 0A 00 00 00 05 00 00 00 08 00 00 00
When I expect:
61 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0A 00 00 00 05 00 00 00 08 00 00 00
Does anyone have an idea why it might happen?
0A is the line feed character and 0D is the carriage return. These are usually associated with text mode.
Have you opened the file in binary mode? (e.g. fopen("foo.txt", "wb"))
When you open the file, open for writing as binary "wb":
fopen(filename, "wb");
When you open in text mode, translation of Line Feeds (0A) and Carriage Returns (0D) occurs.
fopen the file in binary mode with "wb".
fopen(filename, "wb");
otherwise, the code in the library will do automatic line end translation (on windows you are on Windows, are you not? that means translate '\n' to '\r' '\n').
I believe that your inputStr variable contains a newline character and it is written to the binary file as carriage return and linefeed - binary '0D' followed by '0A'.
For eg, the following program writes 16 characters and 3 numbers as follows.
FILE *fp;
fp = fopen("sample.bin", "wb+");
if(fp == NULL)
{
printf("Cannot create a file\n");
return;
}
int i;
char c[1] = {'A'};
for(i = 0; i < 16; i++)
{
fwrite(c, sizeof(char), 1, fp);
c[0]++;
}
int ip[1] = {1};
fwrite(ip, sizeof(int), 1, fp);
fwrite(ip, sizeof(int), 1, fp);
fwrite(ip, sizeof(int), 1, fp);
fclose(fp);
If the 'sample.bin' file is viewed using a dump program such as 'od', it gives the content as follows.
od -t x1 -c sample.bin
0000000 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50
A B C D E F G H I J K L M N O P
0000020 01 00 00 00 01 00 00 00 01 00 00 00
001 \0 \0 \0 001 \0 \0 \0 001 \0 \0 \0
0000034
MS-DOS (and so today with Windows), when writing a file in text mode, adds an 0x0D before every 0x0A. In other words, it processes arbitrary data streams as they go to and from store and messes with their data - utterly, utterly insane.
Open the file in binary mode for non-insane handling.
This code
#include <stdio.h>
#define SECTORSIZE 512 // bytes per sector
int main(int argc, char *argv[])
{
FILE *fp; // filepointer
size_t rdcnt; // num. read bytes
unsigned char buffer[SECTORSIZE];
if(argc < 2)
{
fprintf(stderr, "usage:\n\t%s device\n", argv[0]);
return 1;
}
fp = fopen(argv[1], "rb");
if(fp == NULL)
{
fprintf(stderr, "unable to open %s\n",argv[1]);
return 1;
}
rdcnt = fread(buffer, 1, SECTORSIZE, fp);
if(rdcnt != SECTORSIZE)
{
fprintf(stderr, "reading %s failed\n", argv[1]);
fclose(fp);
return 1;
}
fwrite(buffer, 1, SECTORSIZE, stdout);
fclose(fp);
return 0;
}
kindly taken from here
https://redeaglesblog.wordpress.com/2011/04/05/sektoren-eines-datentragers-lesen/
reads the boot sector from any given disk
Pasted as it is in your preferred C (ANSI) IDE or editor, it compiles and works either in windows (mingw passing \.\PhysicalDriveX) and linux (gcc passing /dev/sdX)
But it works like a charm ONLY in Linux while it anyway inserts/adds an x0D preceding any x0A despiting the fp = fopen(argv[1], "rb");
I've compiled it from code::blocks with mingw as readsect.exe and run it reading the boot sector of my hard drive
c:\readsect.exe \\.\PhysicalDrive0 > read.bin
The file read.bin results with a lenght of 515 bytes instead than 512.
With an HEX editor able to open physical drives, I've compared my boot sector content with the read.bin one.
Well, every x0A in the physical boot sector (x0A is found 3 times), in the read.bin file is dumped as x0D + X0A. So I have three x0D, three bytes more.
Googleing, it looks like a widely reported problem.
Do any of you have found a fix?
Maybe stdio.h needs a fix for the windows environment?
Thank you