I want to print the position of every array in a binary file. The structure of the array is: n, then n numbers (all long, n too).
This is the code:
int main() {
FILE \*f = fopen("a.bin", "rb");
while(!feof(f)) {
printf("-(%d)\\n", ftell(f));
long n; fread(&n, 1, sizeof(long), f);
fseek(f, n \* sizeof(long), SEEK_CUR);
}
}
My idea was to read until the end of the file, but it loops infinitely.
Related
Let's say I have a file:
file.in:
3 3
and I want to read the 2 numbers that are written in it with fread, so I write this:
#include <stdio.h>
int main() {
int buffer[3] = {0}; // 3 items bcs it also reads the space between the "3"s
FILE* f = fopen("file.in", "r");
fread(buffer, 3, 4, f);
printf("%d %d", buffer[0], buffer[2]);
}
I think the output should be 3 3, but I am getting somethink like 17?????? 17??????. But if I make int buffer[3] = {0}; to char buffer[3] = {'\0'}; it works fine
Any attemt to help is appreciated
fread() is for reading the byte stream from the files. 3 3 is represented using 3bytes 0x33 0x20 0x33 if ASCII is used, so fread(buffer, 3, 4, f); (read 12 bytes) is not for reading this.
If you want to store the bytes in int, you should use fgetc() instead.
#include <stdio.h>
int main() {
int buffer[3] = {0}; // 3 items bcs it also reads the space between the "3"s
FILE* f = fopen("file.in", "r");
for (int i = 0; i < 3; i++) {
buffer[i] = fgetc(f);
}
printf("%c %c", buffer[0], buffer[2]); // use %c instead of %d to print the characters corresponding to the character codes
}
I am applying a basic tutorial on image processing in C and I am having problems with this program to convert RGB into grayscale but the output pic is somehow corrupted and although the code runs with no errors, and I cant put my hands on the problem. The code is below.
FILE *fIn = fopen("tiger.bmp","rb"); //Input File name
FILE *fOut = fopen("tiger_gray.bmp","wb"); //Output File name
int i,j,y;
unsigned char byte[54];
if(fIn==NULL)
{
printf("File does not exist.\n");
}
for(i=0;i<54;i++) //read the 54 byte header from fIn
{
byte[i] = getc(fIn);
}
fwrite(byte,sizeof(unsigned char),54,fOut); //write the header back
// extract image height, width and bit Depth from image Header
int height = *(int*)&byte[18];
int width = *(int*)&byte[22];
int bitDepth = *(int*)&byte[28];
printf("width: %d\n",width);
printf("height: %d\n",height );
int size = height*width;
unsigned char buffer[size][3]; //to store the image data
for(i=0;i<size;i++) //RGB to gray
{
y=0;
buffer[i][2]=getc(fIn); //blue
buffer[i][1]=getc(fIn); //green
buffer[i][0]=getc(fIn); //red
y=(buffer[i][0]*0.3) + (buffer[i][1]*0.59) + (buffer[i][2]*0.11); //conversion formula of rgb to gray
putc(y,fOut);
putc(y,fOut);
putc(y,fOut);
}
fclose(fOut);
fclose(fIn);
There were two major problems in your code.
You had the width and height reversed.
You were not accounting for
the required padding at the end of every row to make it a multiple
of 4 bytes.
You were also allocating a large buffer that you did not need based on how the rest of the code was written. Generally I'd prefer to read/process either one full row at a time or even the full image at once, but to do that you want to use malloc or calloc because the data may be larger than the available stack. In this case, to keep things simple, I just process one pixel at a time.
I also got rid of getc/putc because I prefer fread/fwrite and you're never really dealing with 1 byte at a time.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fIn = fopen("tiger.bmp", "rb");
FILE *fOut = fopen("tiger_gray.bmp", "wb");
if (!fIn || !fOut)
{
printf("File error.\n");
return 0;
}
unsigned char header[54];
fread(header, sizeof(unsigned char), 54, fIn);
fwrite(header, sizeof(unsigned char), 54, fOut);
int width = *(int*)&header[18];
int height = abs(*(int*)&header[22]);
int stride = (width * 3 + 3) & ~3;
int padding = stride - width * 3;
printf("width: %d (%d)\n", width, width * 3);
printf("height: %d\n", height);
printf("stride: %d\n", stride);
printf("padding: %d\n", padding);
unsigned char pixel[3];
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
fread(pixel, 3, 1, fIn);
unsigned char gray = pixel[0] * 0.3 + pixel[1] * 0.58 + pixel[2] * 0.11;
memset(pixel, gray, sizeof(pixel));
fwrite(&pixel, 3, 1, fOut);
}
fread(pixel, padding, 1, fIn);
fwrite(pixel, padding, 1, fOut);
}
fclose(fOut);
fclose(fIn);
return 0;
}
I can read unsigned ints from a binary file but one of the values is printing out negative.
Expected values:
45788331,
281302247,
461354227,
13127,
299215653,
2356985123,
Values printed out:
45788331,
281302247,
461354227,
13127,
299215653,
-1932982173,
The 6th value is printing out as negative but I am reading a list of unsigned ints?
My code below
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE * fp;
ssize_t read;
int r = 0;
fp = fopen("numbers.bin", "rb");
if (fp == NULL)
exit(-1);
while(fread(&r, sizeof(unsigned int), 1, fp) == 1)
{
printf("%d\n", r);
}
fclose(fp);
if (line) free(line);
exit(0);
}
printf("%d\n", r); prints out a signed decimal integer.
You want: printf("%u\n", r);
Additionally, r is declared as int not unsigned int.
Type of r is int. The range for the 32 bit int is -2147483648 = -(2^32)/2 through 2147483647 = (2^32)/2 -1 decimal.
2356985123 is outside the range for the signed int. When printing r by printf("%d\n", r); r will be presented as -1937982173.
-1937982173 = 2356985123 - 2^32
I am generating 500 random points (each point is of dimension=4) and writing them into a binary file as the following:
FILE *fp = fopen("file.bin", "wb+");
float *buf = (float *) calloc(500 * 4, sizeof(float));
srand(1);
for (i = 0; i < (500 * 4); ++i) {
buf[i] = (float) rand() / (float) RAND_MAX; // Later I shall treat every 4 values as one point.
}
fwrite(buf, sizeof(float), 500 * 4 * sizeof(float), fp);
fclose(fp);
Later in my code, I want to read only the first 100 points (i.e., 100*4 as each point is of dim=4). I use the following code to do so but I am having a problem and it does not really print anything:
FILE *fp = fopen("file.bin", "rb+");
fseek(fp, 0, SEEK_SET);
int c, cnt=0;
while(1)
{
c = fgetc(fp);
if(feof(fp) || (cnt == 100)) { break; }
printf("%c", c);
cnt++;
}
printf("\n");
fclose(fp);
If you want to read back just 100 elements (as in 4 floats), that's the number you put into fread like so...
fread(buf, sizeof(float), 100 * 4, fp);
as per the various comments above your call to fwrite should look similar as you don't need the extra sizeof(float)
fwrite(buf, sizeof(float), 500 * 4, fp);
basically my problem is that when I use the following program:
#include <stdlib.h>
#include <stdio.h>
#define SIZE 1000
int main() {
FILE *fp;
int r, i;
char fp_string[600] = "/Users/mac/Library/Mobile Documents/com~apple~CloudDocs/College/Program With Persistent Data/Lab 3/num1000.bin";
fp = fopen(fp_string, "rb+");
r = 11;
fseek(fp, 3 * sizeof(int), SEEK_SET);
fwrite(&r, sizeof(int), 1, fp);
fseek(fp, 10 * sizeof(int), SEEK_SET);
fwrite(&r, sizeof(int), 1, fp);
fclose(fp);
return 0;
}
It updates the binary file (which is 1000 integers) with the 3rd and 10th digits to be 11.
But when I do the following:
#include <stdlib.h>
#include <stdio.h>
#define SIZE 1000
int main() {
FILE *fp;
int r, i;
char fp_string[600] = "/Users/mac/Library/Mobile Documents/com~apple~CloudDocs/College/Program With Persistent Data/Lab 3/num1000.bin";
fp = fopen(fp_string, "rb+");
r = 11;
printf("\n\n Before making any changes:\n");
for (i = 0; i < SIZE; i++) {
fseek(fp, i * sizeof(int), SEEK_SET);
fread(&r, sizeof(int), 1, fp);
printf("%d ", r);
}
fseek(fp, 3 * sizeof(int), SEEK_SET);
fwrite(&r, sizeof(int), 1, fp);
fseek(fp, 10 * sizeof(int), SEEK_SET);
fwrite(&r, sizeof(int), 1, fp);
printf("\n\n After making changes:\n");
fseek(fp, 0, SEEK_SET);
for (i = 0; i < SIZE; i++) {
fread(&r, sizeof(int), 1, fp);
printf("%d ", r);
}
fclose(fp);
return 0;
}
It doesn't change anything at all. Just in case you where wondering, to check if the first program worked what I did is:
I would run the program you have underneath this text to check the integers stored in the binary file.
I would run the program you have on top of this text (the second one I posted) to change the 3rd and 10th integer to 11.
I would run the program you have underneath to check that those integers were changed to 11.
That way it worked, but the first program doesn't seem to change anything, it shows the exact same numbers again.
#include <stdlib.h>
#include <stdio.h>
#define SIZE 1000
int main() {
FILE *fp;
int r, i;
char fp_string[600] = "/Users/mac/Library/Mobile Documents/com~apple~CloudDocs/College/Program With Persistent Data/Lab 3/num1000.bin";
fp = fopen(fp_string, "rb");
for (i=0;i<SIZE;i++) {
fread(&r, sizeof(int), 1, fp);
printf("%d ", r);
}
fclose(fp);
return 0;
}
The first for loop is reading every number in the file into rbefore printing them. At the end of the loop, r contains the last number in the file, and that gets written into the places where you seek.
Either use a different variable in the loop, or put the r = 11; assignment after the loop.