Reading and writing integers to a binary file using C? - c

I am trying to write 100 integers to binary file. I have tried writing to this file, and reading from it. When reading from it I get completely random digits.
Here is the block concerning the write.
Do note I have the file open for write with "wb" mode. I have also closed the file at the end.
for (int i = 0; i < 99; i++) {
fwrite(&i, sizeof(int), 1, file);
}
Here is the block concerning the read.
Do note I do have the file open here in "rb" mode and it is closed.
int num;
for (int i = 0; i < 100; i++) {
int rc = getc(file);
if (rc == EOF) {
fputs("Error occured while reading file", stderr);
return EXIT_FAILURE;
}
fread(&num, sizeof(int), 1, file);
printf("%d", num);
}
My output is like this:
-13421772802147469895-168955699232767012640583688388440-104919389914260634872147467638000128293273683884400-19797114882147440795-168947558432767-1097029212883066888388440148657280313254001912147440795-168942592032767-109702911303445504838844014865730434362077432147440795-168935577632767-1097029063753420883766251486573257-6039796492147440795-168932864032767-109702901326841856838844014865733541270-168949760032767-10970289133241241683884401486573450-1090518913214744079500196944831217016018891752457584192041348617175279241952408940298110176910929517683167731702125413116313304413809989891296126535181930809719192433591818324585127960891517680423011935761967-13421772802147469895-168955699232767012640583688388440-104919389914260634872147467638000128293273683884400-19797114882147440795-168947558432767
So there is something wrong, and I am not sure what exactly. Perhaps I am not sure if I understand the API for reading/writing completely (specifically size_t nitems)? I am not sure how to tell how many bytes I need to read/write from a file.

In the first loop, you are writing 100 integers starting at the address of 'i', 99 times.
Not what I think you were thinking you were doing.
it should be
fwrite(&i, sizeof(int), 1, file);
Secondly, what mode do you open the file for writing? It should be opened in binary mode otherwise it will not save binary data correctly (add 'b' to the fopen mode value)
DO you close and reopen the file for the read (and set the right file mode?) or if I was left open, do you fseek back to beginning of the file before trying to read the values.

Related

Reading a text file full with null characters and texts using fread

I am trying to design a small file system.
I have created a text file to store the files data in.
int kufs_create_disk(char* disk_name, int disk_size){
FILE* file_ptr = fopen(disk_name, "w");
if (file_ptr == NULL)
return -1;
fseek (file_ptr, disk_size * 1024-1, SEEK_SET);
fwrite("", 1, sizeof(char), file_ptr); // to make a size for the file
fclose(file_ptr);
DiskName=disk_name;
return 0;
}
After writing to the file I get a file with the size I determine when I call the function.
kufs_create_disk("test.txt", 5);
which creates a file with size of 5kbs with '\0' to fill this file to the size.
I have created another function to write to this file in different places of the file which works just fine and I won't paste the code for simplicity.
When I try to read from the file using fread(), I'm not getting all the data I have written into the memory; rather I get just some of the data.
My read implementation would be:
int kufs_read(int fd, void* buf, int n){
FILE *file_ptr= fopen("test.txt","a+");
fseek (file_ptr, FAT[fd].position, SEEK_SET); //where FAT[fd].position is where I want to start my read and fd is for indexing purposes
fread(buf, 1, n, file_ptr); //n is the number of bytes to be read
FAT[fd].position = FAT[fd].position + n;
}
The thing is the file reads some of the characters written and doesn't read the rest. I did a little test by looping all over the file and checking whether every thing is being read and fread reads every thing but in the buf I only get some of the characters I've written.
The text file looks something like this:
0\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00written string1written string2 0\00\00\00\00\00\00\00\00\00\00\00\000\00\00\00\00\00\00\00\00\00\00\00\00writtenstring 3 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00
I get writtenstring1 and writtenstring2 in the buffer but I don't get writtenstring 3 for example.
Can you explain why?

fread() returns incorrect data

I am trying to read 128KB binary file in chunks of 256 Bytes. The first 20-40 bytes of 256 bytes seems to be always correct. However after that the data gets corrupted. I tried reading the file and writing it into another binary file and compared. More than half of the data is corrupted. Here is my code
uint8_t buffer[256]
read_bin_file = fopen("vtest.bin", "r");
if (read_bin_file == NULL)
{
printf("Unable to open file\n");
return false;
}
test_bin = fopen("test_file.bin", "w");
if (test_file == NULL)
{
printf("Unable to open file\n");
return false;
}
fflush(stdout);
for (i = 0; i <=0x1FF; i++)
{
file_Read_pointer = i * 256;
fseek(read_bin_file, file_Read_pointer, SEEK_SET);
fread(buffer, 256, 1, read_bin_file);
fseek(test_file, file_Read_pointer, SEEK_SET);
fwrite(buffer, 256, 1, test_file);
}
What is that I am missing?
Also when i try to increase the bytes read from 256 to 1024 ( i<0x7F) the error seems to decrease significantly. The file is almost 90% matching
If it is binary data you're reading and writing, then you should open the files in binary mode with read_bin_file = fopen("vtest.bin", "rb");. Note the "b" in the mode. This prevents special handling of new line characters.
Your fseeks are also unnecessary, the fread and fwrite calls will handle that for you.
From here "The file position indicator for the stream is advanced by the number of characters read."

fscanf while-loop never runs

I'm working on a project, and I can't seem to figure out why a piece of my function for finding prime numbers won't run. Essentially, I want to code to first check the text file log for any previously encountered prime numbers, but no matter what I put for the while-loop containing fscanf(), it seems like my code never enters it.
int filePrime(int a) {
int hold = 0;
FILE *fp = fopen("primes.txt", "a+");
if (fp == NULL) {
printf("Error while opening file.");
exit(2);
}
/*
the while loop below this block is the one with the issue.
on first run, it should skip this loop entirely, and proceed
to finding prime numbers the old-fashioned way, while populating the file.
instead, it is skipping this loop and proceeding right into generating a
new set of prime numbers and writing them to the file, even if the previous
numbers are already in the file
*/
while (fscanf(fp, "%d", &hold) == 1){
printf("Inside scan loop.");
if (hold >= a) {
fclose(fp);
return 1;
}
if (a % hold == 0) {
fclose(fp);
return 0;
}
}
printf("Between scan and print.\n");
for (; hold <= a; hold++) {
if (isPrime(hold) == 1) {
printf("Printing %d to file\n", hold);
fprintf(fp, "%d\n", hold);
if (hold == a)
return 1;
}
}
fclose(fp);
return 0;
}
I have tried all sorts of changes to the while-loop test.
Ex. != 0, != EOF, cutting off the == 1 entirely.
I just can't seem to get my code to enter the loop using fscanf.
Any help is very much appreciated, thank you so much for your time.
In a comment, I asked where the "a+" mode leaves the current position?
On Mac OS X 10.11.4, using "a+" mode opens the file and positions the read/write position at the end of file.
Demo code (aplus.c):
#include <stdio.h>
int main(void)
{
const char source[] = "aplus.c";
FILE *fp = fopen(source, "a+");
if (fp == NULL)
{
fprintf(stderr, "Failed to open file %s\n", source);
}
else
{
int n;
char buffer[128];
fseek(fp, 0L, SEEK_SET);
while ((n = fscanf(fp, "%127s", buffer)) == 1)
printf("[%s]\n", buffer);
printf("n = %d\n", n);
fclose(fp);
}
return(0);
}
Without the fseek(), the return value from n is -1 (EOF) immediately.
With the fseek(), the data (source code) can be read.
One thing slightly puzzles me: I can't find information in the POSIX fopen() specification (or in the C standard) which mentions the read/write position after opening a file with "a+" mode. It's clear that write operations will always be at the end, regardless of intervening uses of fseek().
POSIX stipulates that the call to open() shall use O_RDWR|O_CREAT|O_APPEND for "a+", and open() specifies:
The file offset used to mark the current position within the file shall be set to the beginning of the file.
However, as chux notes (thanks!), the C standard explicitly says:
Annex J Portability issues
J.3 Implementation-defined behaviour
J.3.12 Library functions
…
Whether the file position indicator of an append-mode stream is initially positioned at
the beginning or end of the file (7.21.3).
…
So the behaviour seen is permissible in the C standard.
The manual page on Mac OS X for fopen() says:
"a+" — Open for reading and writing. The file is created if it does not exist. The stream is positioned at the end of the file. Subsequent writes to the file will always end up at the then current end of file, irrespective of any intervening fseek(3) or similar.
This is allowed by Standard C; it isn't clear it is fully POSIX-compliant.

C sockets receive file

I'm developing very simple ftp client. I have created a data connection sockets, but I can't transfer file successfully:
FILE *f = fopen("got.png", "w");
int total = 0;
while (1){
memset(temp, 0, BUFFSIZE);
int got = recv(data, temp, sizeof(temp), 0);
fwrite(temp, 1, BUFFSIZE, f);
total += got;
if (total == 1568){
break;
}
}
fclose(f);
BUFFSIZE = 1568
I know that my file is 1568 bytes size, so I try to download it just for a test. Everything is file when I try to download .xml or .html files, but nothing good happens when I try to download png or avi files. Simply original file size is 1568 but got.png file size is 1573. I can't figure out what might cause that.
EDIT:
I have modified my code, so now it looks like (it can accept any file size):
FILE *f = fopen("got.png", "w");
while (1){
char* temp = (char*)malloc(BUFFSIZE);
int got = recv(data, temp, BUFFSIZE, 0);
fwrite(temp, 1, got, f);
if (got == 0){
break;
}
}
fclose(f);
Still received file is 2 bytes too long.
You are opening the file in text mode, so bare CR/LF characters are going to get translated to CRLF pairs when written to the file. You need to open the file in binary mode instead:
FILE *f = fopen("got.png", "wb");
You are always writing a whole buffer even if you have received only a partial one. This is the same problem with ~50% of all TCP questions.
The memset is not necessary. And I hope that temp is an array so that sizeof(temp) does not evaluate to the native pointer size. Better use BUFFSIZE there as well.
Seeing your edit, after fixing the first problem there is another one: Open the file in binary mode.

Writing data to a binary file, then reading it back

I am trying to write data to a binary file and then read back the data from the file. The data consists of a single number (an integer) nrows. Below is my code for writing the data to a binary file. However, when I try to read back the data and print the result using printf, I obtain a nonsensical result: -2.
FILE *fout;
FILE *file_pointer;
int nrows = 5;
fout = fopen("matrixB.bin", "wb") //Writing to a binary file.//
fwrite(&nrows, sizeof(int), 1, fout); //Writing the number nrows to the binary file "matrixB.bin"//
file_pointer = fopen("matrixB.bin", "rb"); //Reading a binary file.//
fread(&nrows, sizeof(int), 1, file_pointer);
printf("%d", nrows); //Here -2 is printed, instead of 5.//
What is the problem with my code?
One of the characteristics of the C file functions (fread, fwrite, etc) is that they normally perform buffered I/O.
Your program doesn't flush and/or close the file before reopening it. It should.

Resources