I have to read a png file(in binary) and i have to get out height and width of the picture(starting as 17 and long 8bytes together).
i tried
FILE* picture = fopen("test.png","rb");
fseek(picture, 16 , SEEK_SET);
int counter = 0;
while(counter < 8){
fscanf(picture, "%d", temp[counter]);
counter++;
}
but no luck
You should never read binary files using the file-library, but rather the system-calls read and write.
void* buf = malloc(1024);
memset(buf,0,1024);
int picturefd = open("test.png",O_RDONLY);
lseek(picturefd, 16 , SEEK_SET);
if(read(picturefd, buf, 8) < 8){
//failed to read or eof reached
}
See here for read and here for lseek.
Related
Currently I am trying to read a binary file 16 bytes at a time. This is great until the end of the file where it reads a full 16 bytes regardless of whether the file has ended or not. I have a file with "ABCDEFGHIJKLMNOPQRSTUV" written into it and it reads "QRSTUVGHIJKLMNOP" on the second pass after successfully receiving the first 16. How can I stop it from re reading those bytes? This is what I have currently. It obviously does not print the second pass of data because fread does not return 16. I should note I MUST read 16 bytes at a time.
#define BS 16
unsigned char buffer[BS]; // for storing each 16 bytes read
int i = 0; // for iterating through readbytes
while (fread(buffer, 1, sizeof(buffer), ifp) == BS) {
while (i < BS) {
printf("Read: %c\n",buffer[i]);
i++;
}
i = 0;
}
It doesn't reread the bytes GHI…NOP; they are still in the buffer from the previous successful read. When fread() reports a short read, the contents of the buffer after the data it reports reading are indeterminate. You need to save the return value from fread() — it's a size_t — and use that to guide you. It reports 6 bytes; accessing anything after that leads to undefined (unspecified, indeterminate — generically 'undesirable') behaviour.
You should define int i = 0; inside the outer while loop; then you wouldn't need the trailing i = 0; after the inner loop. Or even just a routine for loop, as M.M commented.
Hence:
#define BS 16
unsigned char buffer[BS];
size_t nbytes;
while ((nbytes = fread(buffer, 1, sizeof(buffer), ifp)) == BS)
{
for (size_t i = 0; i < BS; i++)
printf("Read: %c\n", buffer[i]);
}
printf("Short read (%zu bytes):\n", nbytes);
for (size_t i = 0; i < nbytes; i++)
printf("Short: %c\n", buffer[i]);
I'm having an issue trying to convert a Binary File into a text file. Right now, I'm getting an output of "hello 16". I should be getting 5 lines of output, in which the first line should be "hello 32". I'm unsure where I went wrong, but I've been trying to figure it out for a few hours now.
Link to Binary File
void BinaryToText(char *inputFile, char *outputFile) {
unsigned char str[256];
unsigned int num;
int fileLen;
FILE *finp;
FILE *fout;
finp = fopen(inputFile, "r");
fout = fopen(outputFile, "w");
fseek(finp, 0, SEEK_END);
fileLen = ftell(finp);
fseek(finp, 0, SEEK_SET);
while (fread(&fileLen, sizeof(char), 1, finp) == 1) {
fread(&str, sizeof(str), 1, finp);
fread(&num, sizeof(int), 1, finp);
fprintf(fout, "%s %d\n", str, num);
}
fclose(finp);
fclose(fout);
}
You binary file format seems awkward:
you open the input file with "r": it should be opened in binary mode with "rb".
you first attempt to determine the file size with ftell(). Be aware that this will not work for pipes and devices. In you case it would not matter as you do not use fileLen anyway.
in the loop:
you read a single byte that you store in a part of fileLen.
you then read a string of 256 bytes.
you read a number directly, assuming the byte order and size of int is what you expect.
you then print the string, assuming there was a '\0' in the file, otherwise you would invoke undefined behavior.
It is hard to tell what is wrong without seeing the writing code.
Note that the binary file should be open with "rb" to prevent spurious conversion of linefeed sequences on some platforms, notably Windows.
EDIT:
Form the extra information provided in the comments, here is a modified version that should parse you binary file more appropriately:
void BinaryToText(char *inputFile, char *outputFile) {
unsigned char str[256];
unsigned int num; // assuming 32 bit ints
int i, len;
FILE *finp = fopen(inputFile, "rb");
FILE *fout = fopen(outputFile, "w");
while ((len = fgetc(finp)) != EOF) {
fread(str, len, 1, finp);
str[len] = '\0';
num = (unsigned int)fgetc(finp) << 24;
num |= fgetc(finp) << 16;
num |= fgetc(finp) << 8;
num |= fgetc(finp);
fprintf(fout, "%s %d\n", (char*)str, num);
}
fclose(finp);
fclose(fout);
}
I have a binary file that contains 16-bit integer data and i want to convert it to ASCII readable data.
My question is how do I use fread(&buffer,sizeof(buffer) or 16,1,fp); to read the file and use again fwrite(buffer, sizeof(buffer)/7, 1, file); to write the data to a file.
16 in fread is 16-bit and wants to know where it goes or in what form it goes and if in fwrite I will put 7 for 7-bit.
Please provide a code snippet example in C. I want to have the resultant file to be an ordinary readable text file.
You have many things that are confusing.
Assuming buffer is a magically sized properly to fit the file uint8_t array, you can read it in (from a file fopen()ed in binary mode) using:
fread(buffer, sizeof buffer, in);
That'd give you all of the bits in buffer, if it doesn't fail.
Then, the output is simply:
FILE * const out = fopen("numbers.txt", "wt");
if(out != NULL)
{
for(size_t i = 0; i < sizeof buffer; i += 2)
{
const unsigned int here = buffer[i] + 256 * buffer[i + 1];
fprintf(out, "%u\n", here);
}
fclose(out);
}
This assumes little-endian byte ordering in the binary file. Swap the indexes in the here assignment for big-endian. It also assumes unsigned 16-bit numbers.
after adjusing my code as below the result i get unsigned int,since am expecting data result with alphabetical characters.what additional code can i add to turn it alphabetical?
#include<stdio.h>
int main()
{
FILE *fp,*out;
char buffer[256];
size_t i = 0;
fp=fopen("c:/Gosam/input.txt", "rb");
if(out != NULL)
{
fread(buffer, sizeof buffer,1, fp);
}
out = fopen("c:/Gosam/res.txt", "w");
if(out != NULL)
{
// buffer = (char*) malloc (sizeof(char)*Size);
for( i = 0; i < sizeof(buffer); i += 2)
{
const unsigned int var = buffer[i] + 256 * buffer[i + 1];
fprintf(out, "%u\n", var);
}
fclose(out);
}
fclose(fp);
}
these are my results but i want to turn them to alphabetical strings.
263
4294966987
4294967222
4294967032
64
4294967013
73
4294967004
90
4294967028
83
4294966975
37
4294966961
5
4294966976
82
4294966942
4294967022
4294966994
11
4294967024
29
4294966985
4294966986
4294966954
The following code writes an array of unsigned char (defined as byte) to a file:
typedef unsigned char byte;
void ToFile(byte *buffer, size_t len)
{
FILE *f = fopen("out.txt", "w");
if (f == NULL)
{
fprintf(stderr, "Error opening file!\n");
exit(EXIT_FAILURE);
}
for (int i = 0; i < len; i++)
{
fprintf(f, "%u", buffer[i]);
}
fclose(f);
}
How do I read the file back from out.txt into a buffer of byte? The goal is to iterate the buffer byte by byte. Thanks.
If you want to read it back, I wouldn't use %u to write it out. %u is going to be variable width output, so a 1 takes one character, and a 12 takes two, etc. When you read it back and see 112 you don't know if that's three characters (1, 1, 2), or two (11, 2; or 1, 12) or just one (112). If you need an ASCII file, you would use a fixed width output, such as %03u. That way each byte is always 3 characters. Then you could read in a byte at a time with fscanf("%03u", buffer[i]).
How do I read the file back from out.txt into a buffer of byte? The goal is to iterate the buffer byte by byte. Thanks.
Something similar to this should work for you. (Not debugged, doing this away from my compiler)
void FromFile(byte *buffer, size_t len)
{
FILE *fOut = fopen("out.txt", "rb");
int cOut;
int i = 0;
if (fOut == NULL)
{
fprintf(stderr, "Error opening file!\n");
exit(EXIT_FAILURE);
}
cOut = fgetc(fOut);
while(cOut != EOF)
{
buffer[i++] = cOut; //iterate buffer byte by byte
cOut = fgetc(fOut);
}
fclose(fOut);
}
You could (and should) use fread() and fwrite() (http://www.cplusplus.com/reference/cstdio/fread/) for transferring raw memory between FILE s and memory.
To determine the size of the file (to advise fread() how many bytes it should read) use fseek(f, 0, SEEK_END) (http://www.cplusplus.com/reference/cstdio/fseek/) to place the cursor to the end of the file and read its size with ftell(f) (http://www.cplusplus.com/reference/cstdio/ftell/). Don't forget to jump back to the beginning with fseek(f, 0, SEEK_SET) for the actual reading process.
I have a binary file and I will be using fread to read the data from this binary file into an array of structures.
However, I don't know what value to pass to fread as its second argument. I know the file size is 536870912 bits. The binary file was constructed on the basis of being accessed for a 512^3 array. This means each data entry is of type float in the binary file with 4 bytes specified for each data element.
I made an error with the mention of bits. I read what was outputted by a C program finding the size of the file - it outputted 536870912 bits! Apologies to anyone confused.
Here is the code i'm using to read the data from the binary file into my arrary of structures (a simplified structure - there are 10 other parameters!)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
// Define the model structure
struct model {
float density;
};
// Entry point for the program
int main () {
int counter;
long lSize;
char * buffer;
size_t result;
FILE *pFile;
int i,j,k,ibox; /* Loop indices for the physical grid */
struct model ***mymodel;
pFile = fopen("core1_dens_0107.bin","rb");
if (pFile == NULL) { printf("Unable to open density file!"); exit(1); }
// obtain file size:
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
printf( "File size : %lu Bits \n", lSize );
for ( j = 0 ; j < 512 ; j++ ) {
for ( k = 0; k < 512; k++ ) {
for ( i = 0; i < 512; i++ ) {
fread(&mymodel[i][j][k].density,4,1,pFile);
printf("%f \n",mymodel[i][j][k].density);
}
}
}
fclose(pFile);
return 0;
}
Supposing you have already opened the file and you have your file descriptor myStream, it should be as simple as this:
#define MY_DIM = 512; ///Maybe you want to play safe and make it a little bit larger? Up to you
float buffer[MY_DIM][MY_DIM][MY_DIM];
size_t readBytes;
int i,j,k;
for (k = 0; k < MY_DIM; k++)
for (j = 0; j < MY_DIM; j++) {
readBytes = fread((void*) (buffer[k][j]), sizeof float, MY_DIM, myStream); //I am not sure the (void*) conversion is necessary
if (readBytes < MY_DIM) //I unexpectedly reached the end of the file,
goto endOfTheLoop; //without reading all the data I needed for int
//You could also print a warning message
}
endOfTheLoop:
//Now close the input file, use fclose or something
//Now that you have read all the data, you have to put it in your array of struct:
for (k = 0; k < MY_DIM; k++)
for (j = 0; j < MY_DIM; j++)
for (i = 0; i < MY_DIM; i++)
mymodel[k][j][i].density = buffer[k][j][i];
You can pass whatever value of the 2nd argument is most convenient for your program. If you want to process the file one structure at a time, do:
nread = fread(&your_struct, 1, sizeof yourstruct, stream);
If you have an array of structures, e.g.
struct foo your_struct[STRUCT_COUNT];
you can do:
nread = fread(your_struct, STRUCT_COUNT, sizeof *your_struct, stream);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE * stream );
will attempt to read nmemb blocks of size bytes each. It will guarantee that no partial blocks are read. If your blocks are 4 bit long then I suggest you read them byte by byte, otherwise use the size argument to specify the block size.
For instance
fread(buffer, 1, 1024, stdin);
will attempt to read 1024 bytes, but may stop at any point.
fread(buffer, 4, 256, stdin);
will attempt to also read 1024 bytes, but in blocks of 4 bytes. 256 blocks total. It will guarantee that no partial blocks are read.
fread(buffer, 1024, 1, stdin);
will attempt to read one block of 1024 bytes. If it can not - nothing will be read.
If you wish to read in the entire file then you can do it in blocks of 4 via:
size_t read, read_now;
while (read < filesize && (read_now= fread(buffer +read, 4, (filesize - read) >> 2, in)) != EOF)
read += read_now;
of you can attempt to read the whole thing in one go:
fread(buffer, filesize, 1, in);