Strangeness in reading a binary file in C - c

I've defined a binary file like this in C
FILE *gfp;
gfp = fopen(gridfiles, "wb");
The variable gridfiles stores the name of the file, and has been defined earlier. Now I write out two variables into the file.
for(yy = 0; yy < nfiley; yy++) {
for(xx = 0; xx < nfilex; xx++) {
filebx = beguv + xx*1E3;
fileby = enduv - yy*1E3;
fwrite(&filebx, sizeof(filebx), 1, gfp);
fwrite(&fileby, sizeof(fileby), 1, gfp);
}
}
If right after this code I
fseek(gfp, 0, SEEK_SET);
fread(&filebx, sizeof(filebx), 1, gfp);
fread(&fileby, sizeof(fileby), 1, gfp);
fprintf(stderr, "%f %f", filebx, fileby);
my output is
1000 15000
for the first two, which is as expected.
But if after some assorted other code (that doesn't involve these files at all) I repeat the fseek() etc., my output is
14000 14000
regardless of what I do.
I've been trying to figure this out for a while now... anyone know what I'm doing wrong?

It's Undefined Behaviour to read from a stream which has been opened in write mode. You should make it:
gfp = fopen(gridfiles, "wb+");
if you plan to both read and write.
Also, as pointed out by #Kyle Jones in the comments above, you should get into the habit of checking the return status of fread/fwrite when doing file I/O - this would have caught your problem a lot earlier.

Related

Fread function did not read whole file

Hey guys i need to read something from file and put that in buffer, so i use fread function. My code is:
duzina = configs[i].lenght * 1048576;
printf("Duzina %d[B]: %d\n",i+1,duzina);
printf("Duzina %d[MB]: %d\n",i+1,duzina/1048576);
printf("Duzina %d[B]: %d\n",i+1,duzina);
ukupna_duzina = ukupna_duzina + duzina;
printf("Ukupna duzina[B]: %d\n",ukupna_duzina);
printf("Ukupna duzina[MB]: %d\n",ukupna_duzina/1048576);
procitano[i] = fread(buffers[i],1,duzina,fp);
printf("Procitano %d[B]\n",procitano[i]);
perror("PERROR KAZE: ");
fseek(fp,ukupna_duzina,SEEK_SET);
In terminal, i get right size for duzina, 2,097,152B, perror returns no_error, but procitano[i] which is size_t type gives me 2 064 384 B. Also when i open file i need to read from his size is good -> 2,097,152B. So what is happening?

fread returns no data in my buffer in spite of saying it read 4096 bytes

I'm porting some C code that loads sprites from files containing multiple bitmaps. Basically the code fopens the file, fgetcs some header info, then freads the bitmap data. I can see that the fgetcs are returning proper data, but the outcome of the fread is null. Here's the code - fname does exist, the path is correct, fil is non-zero, num is the number of sprites in the file (encoded into the header, little-endian), pak is an array of sprites, sprite is a typedef of width, height and bits, and new_sprite inits one for you.
FILE *fil;
uint8 *buffu;
uint8 read;
int32 x,num;
int32 w,h,c;
fil = fopen(fname, "rb");
if (!fil) return NULL;
num = fgetc(fil);
num += fgetc(fil)*256;
if (num > max) max = num;
for (x=0;x<max;x++) {
// header
w=fgetc(fil);
w+=fgetc(fil)*256;
h=fgetc(fil);
h+=fgetc(fil)*256;
fgetc(fil); // stuff we don't use
fgetc(fil);
fgetc(fil);
fgetc(fil);
// body
buffu = (uint8*)malloc(w * h);
read=fread(buffu,1,w*h,fil);
pak->spr[x]=new_sprite(w,h);
memcpy(pak->spr[x]->data, buffu, w*h);
// done
free(buffu);
}
I've stepped through this code line by line, and I can see that w and h are getting set up properly, and read=4096, which is the right number of bits. However, buffer is "" after the fread, so of course memcpy does nothing useful and my pak is filled with empty sprites.
My apologies for what is surely a totally noob question, but I normally use Cocoa so this pure-C file handling is new to me. I looked all over for examples of fread, and they all look like the one here - which apparently works fine on Win32.
Since fgetc seems to work, you could try this as a test
int each;
int byte;
//body
buffu = malloc(w * h);
for (each = 0; each < w*h; each++) {
byte = fgetc(fil);
if ( byte == EOF) {
printf("End of file\n");
break;
}
buffu[each] = (uint8)byte;
printf ("byte: %d each: %d\n", byte, each);
}
pak->spr[x]=new_sprite(w,h);
memcpy(pak->spr[x]->data, buffu, w*h);
// done
You say:
However, buffer is "" after the fread, so of course memcpy does nothing useful
But that is not true at all. memcpy() is not a string function, it will copy the requested number of bytes. Every time. If that isn't "useful", then something else is wrong.
Your buffer, when treated as a string (which it is not, it's a bunch of binary data) will look like an empty string if the first byte happens to be 0. The remaining 4095 bytes can be whatever, to C's string printing functions it will look "empty".

fgetc not starting at beginning of file - c [duplicate]

This question already has an answer here:
fgetc not starting at beginning of large txt file
(1 answer)
Closed 9 years ago.
Problem solved here:
fgetc not starting at beginning of large txt file
I am working in c and fgetc isn't getting chars from the beginning of the file. It seems to be starting somewhere randomly within the file after a \n. The goal of this function is to modify the array productsPrinted. If "More Data Needed" or "Hidden non listed" is encountered, the position in the array, productsPrinted[newLineCount], will be changed to 0. Any help is appreciated.
Update: It works on smaller files, but doesn't start at the beginning of the larger,617kb, file.
function calls up to category:
findNoPics(image, productsPrinted);
findVisible(visible, productsPrinted);
removeCategories(category, productsPrinted);
example input from fgetc():
Category\n
Diagnostic & Testing /Scan Tools\n
Diagnostic & Testing /Scan Tools\n
Hidden non listed\n
Diagnostic & Testing /Scan Tools\n
Diagnostic & Testing /Scan Tools\n
Hand Tools/Open Stock\n
Hand Tools/Sockets and Drive Sets\n
More Data Needed\n
Hand Tools/Open Stock\n
Hand Tools/Open Stock\n
Hand Tools/Open Stock\n
Shop Supplies & Equip/Tool Storage\n
Hidden non listed\n
Shop Supplies & Equip/Heaters\n
Code:
void removeCategories(FILE *category, int *prodPrinted){
char more[17] = { '\0' }, hidden[18] = { '\0' };
int newLineCount = 0, i, ch = 'a', fix = 0;
while ((ch = fgetc(category)) != EOF){ //if fgetc is outside while, it works//
more[15] = hidden[16] = ch;
printf("%c", ch);
/*shift char in each list <- one*/
for (i = 0; i < 17; i++){
if (i < 17){
hidden[i] = hidden[i + 1];
}
if (i < 16){
more[i] = more[i + 1];
}
}
if (strcmp(more, "More Data Needed") == 0 || strcmp(hidden, "Hidden non listed") == 0){
prodPrinted[newLineCount] = 0;
/*printf("%c", more[0]);*/
}
if (ch == '\n'){
newLineCount++;
}
}
}
Let computers do the counting. You have not null terminated your strings properly. The fixed strings (mdn and hdl are initialized but do not have null terminators, so string comparisons using them are undefined.
Given this sample data:
Example 1
More Data Needed
Hidden non listed
Example 2
Keeping lines short.
But as they get longer, the overwrite is worse...or is it?
Hidden More Data Needed in a longer line.
Lines containing "Hidden non listed" are zapped.
Example 3
This version of the program:
#include <stdio.h>
#include <string.h>
static
void removeCategories(FILE *category, int *prodPrinted)
{
char more[17] = { '0' };
char hidden[18] = { '0' };
char mdn[17] = { "More Data Needed" };
char hnl[18] = { "Hidden non listed" };
int newLineCount = 0, i, ch = '\0';
do
{
/*shift char in each list <- one*/
for (i = 0; i < 18; i++)
{
if (i < 17)
hidden[i] = hidden[i + 1];
if (i < 16)
more[i] = more[i + 1];
}
more[15] = hidden[16] = ch = fgetc(category);
if (ch == EOF)
break;
printf("%c", ch); /*testing here, starts rndmly in file*/
//printf("<<%c>> ", ch); /*testing here, starts rndmly in file*/
//printf("more <<%s>> hidden <<%s>>\n", more, hidden);
if (strcmp(more, mdn) == 0 || strcmp(hidden, hnl) == 0)
{
prodPrinted[newLineCount] = 0;
}
if (ch == '\n')
{
newLineCount++;
}
} while (ch != EOF);
}
int main(void)
{
int prod[10];
for (int i = 0; i < 10; i++)
prod[i] = 37;
removeCategories(stdin, prod);
for (int i = 0; i < 10; i++)
printf("%d: %d\n", i, prod[i]);
return 0;
}
produces this output:
Example 1
More Data Needed
Hidden non listed
Example 2
Keeping lines short.
But as they get longer, the overwrite is worse...or is it?
Hidden More Data Needed in a longer line.
Lines containing "Hidden non listed" are zapped.
Example 3
0: 37
1: 0
2: 0
3: 37
4: 37
5: 37
6: 0
7: 0
8: 37
9: 37
You may check which mode you opened the file, and you may have some error-check to make sure you have got the right return value.
Here you can refer to man fopen to get which mode to cause the stream position.
The fopen() function opens the file whose name is the string pointed to
by path and associates a stream with it.
The argument mode points to a string beginning with one of the follow‐
ing sequences (Additional characters may follow these sequences.):
r Open text file for reading. The stream is positioned at the
beginning of the file.
r+ Open for reading and writing. The stream is positioned at the
beginning of the file.
w Truncate file to zero length or create text file for writing.
The stream is positioned at the beginning of the file.
w+ Open for reading and writing. The file is created if it does
not exist, otherwise it is truncated. The stream is positioned
at the beginning of the file.
a Open for appending (writing at end of file). The file is cre‐
ated if it does not exist. The stream is positioned at the end
of the file.
a+ Open for reading and appending (writing at end of file). The
file is created if it does not exist. The initial file position
for reading is at the beginning of the file, but output is
always appended to the end of the file.
And there is another notice, that the file you operated should not more than 2G, or there maybe problem.
And you can use fseek to set the file position indicator.
And you can use debugger to watch these variables to see why there are random value. I think debug is efficient than trace output.
Maybe you can try rewinding the file pointer at the beginning of your function.
rewind(category);
Most likely another function is reading from the same file. If this solves your problem, it would be better to find which other function (or previous call to this function) is reading from the same file and make sure rewinding the pointer won't break something else.
EDIT:
And just to be sure, maybe you could change the double assignment to two different statements. Based on this post, your problem might as well be caused by a compiler optimization of that line. I haven't checked with the standard, but according to best answer the behavior in c and c++ might be undefined, therefore your strange results. Good luck

Reading from binary file is unsuccessful in C

I am using C programming language and am trying to read the first string of every line in a binary File .
Example of data in the binary file (I have written to a txt file in order to show you)
Iliya Iliya Vaitzman 16.00 israel 1 0 1
I want to read to first Iliya in the line (or what ever the first word in the line will be).
I am trying the following code but it keeps returning NULL to the string variable I gave him
The following code:
FILE* ptrMyFile;
char usernameRecieved[31];
boolean isExist = FALSE;
ptrMyFile = fopen(USERS_CRED_FILENAME, "a+b");
if (ptrMyFile)
{
while (!feof(ptrMyFile) && !isExist)
{
fread(usernameRecieved, 1, 1, ptrMyFile);
if (!strcmp(userName, usernameRecieved))
{
isExist = TRUE;
}
}
}
else
{
printf("An error has encountered, Please try again\n");
}
return isExist;
I used typedef and #define to a boolean variable (0 is false, everything else is true (TRUE is true, FALSE is false))
usernameRecieved keeps getting NULL from the fread .
What should I do in order to solve this?
Instead of this:
fread(usernameRecieved, 1, 1, ptrMyFile);
try this:
memset(usernameRecieved, 0, sizeof(usernameRecieved));
fread(usernameRecieved, sizeof(usernameRecieved)-1, 1, ptrMyFile);
As it is, you are reading at most only one byte from the file.
Documentation on fread
A couple things: you're setting the count field in fread to 1, so you'll only ever read 1 byte, at most (assuming you don't hit an EOF or other terminal marker).
It's likely that what you want is:
fread(usernameRecieved, 1, 31, ptrMyFile);
That way you'll copy into your whole char buffer. You'll then want to compare only up to whatever delimiter you're using (space, period, etc).
It's not clear what "usernameRecieved keeps getting NULL" means; usernameRecieved is on the stack (you aren't using malloc). Do you mean that nothing is being read? I highly suggest that you always check the return value from fread to see how much is read; this is helpful in debugging.

Write to file in C

I'm having trouble transferring data from a file to another file using C, and I would like some help from the community to help me troubleshoot some of the output problems. I'm doing this because I want to convert the txt data into binary data next. Totally testing purpose.
Here is the code I have so far:
int txt2txt()
{
FILE *pTextFile, *pBinaryFile;
char buffer[1000];
pTextFile = fopen ("AS001.txt","r");
pBinaryFile = fopen("BS001.txt","w");
while(fgets(buffer,1000,pTextFile)!=NULL){
fwrite(buffer,sizeof(int),sizeof(buffer),pBinaryFile);
}
fclose(pTextFile);
fclose(pBinaryFile);
return 0;
}
Sample input/output:
AS001.txt:
91829812
1231231
1231232
123231123
1232312
123123123
12312312
and output BS001.txt:
91829812
„w O]€©O] * + O] ¤O]H¨O] ¬O]( O] #¨O]Lü( ¾8„w8O]š8„w¥ex O]ˆ©O] O]8¤O]  ¤O] ¤O]H¨O]`žO]H O] 8¤O]œü( ¾8„w8O]š8„wuex O]#¤O] ЪO]Q ø H¨O]PO] ¬O] O]PO]™Qº€O]PO] D Q Q ¬O] Q ˆ p¨O] ¬O]Õqˆw¹Qºþÿÿÿ|O]
This code:
while(fgets(buffer,1000,pTextFile)!=NULL){
fwrite(buffer,sizeof(int),sizeof(buffer),pBinaryFile);
}
Tries to read 1000 bytes and then writes 1000 * sizeof(int) bytes per iteration. Unless your system has 1-byte integers (unlikely), that's probably not what you wanted.
Besides that, fgets might not have filled up your entire buffer - it stops at a newline.
Use:
while (fgets(buffer, 1000, pTextFile) != NULL)
{
fwrite(buffer, 1, strlen(buffer), pBinaryFile);
}
Edit: Since you're having problems, here's a complete example. First, source code:
#include <stdio.h>
#include <string.h>
int main(void)
{
char buffer[1000];
FILE *pTextFile = fopen("AS001.txt","r");
FILE *pBinaryFile = fopen("BS001.txt","w");
while (fgets(buffer, 1000, pTextFile) != NULL)
{
fwrite(buffer, 1, strlen(buffer), pBinaryFile);
}
fclose(pTextFile);
fclose(pBinaryFile);
return 0;
}
Second, build & run:
$ make example
cc example.c -o example
$ cat AS001.txt
91829812
1231231
1231232
123231123
1232312
123123123
12312312
$ ./example
$ diff AS001.txt BS001.txt
$
Include the string.h from the standard library and change your write command to this:
fwrite(buffer, sizeof(char), strlen(buffer), pBinaryFile);
This will stop it from trying to write the junk data in the rest of the buffer, which is undefined.

Resources