Binary reading returning zero - c

I'm trying to read a binary file and display its contents in the terminal, but this line of code:
size_t readed = fread(buffer, sizeof(buffer), positionX, file);
It is returning zero, so my loop is stopped, what is the suggestion to solve this problem?
buffer = Storage
sizeof(buffer) = Size File
positionX = 7918080 <-- Dynamic Pointer
file = File to read
Terminal output:
https://i.stack.imgur.com/i9pls.png
My complete code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if (argc < 2)
{
printf("Usage: Please insert the file to read\n");
return 1;
}
else
{
FILE *file;
file = fopen(argv[1], "rb");
//Cannot open file --> check pointer file after fopen
if (file == NULL)
{
printf("Cannot open file \n");
exit(0);
}
long positionX = ftell(file);
printf("Pointer at the beginning %ld\n", positionX);
fseek(file, 0, SEEK_END);
positionX = ftell(file);
rewind (file); // Sets the position indicator associated with stream to the beginning of the file
unsigned char buffer[positionX]; // o buffer deveria ser criado aqui depois de pegar a posição final
printf("Pointer at the End: %ld\n", positionX);
// Read the content --> it's always good to check the read value
// the third parameter was 1, it should be "position"
size_t readed = fread(buffer, sizeof(buffer), positionX, file);
printf("the size is %zu\n", readed); // decimal size_t ("u" for unsigned)
printf("the size is %zx\n", readed); // hex size_t
for(size_t i = 0; i < readed; i++) // usar readed como limite
{
printf("%x ", buffer[i]); // prints a series of bytes
}
}
}
Thanks

Your call to fread is incorrect:
size_t readed = fread(buffer, sizeof(buffer), positionX, file);
The second parameter is the size of each element to read, and the third is the number of elements. This means that you're attempting to read up to sizeof(buffer) * positionX bytes, but buffer isn't that big. As a result, you write past the end of the buffer triggering undefined behavior.
Since you're reading positionX individual characters, you want 1 for the member size:
size_t readed = fread(buffer, 1, positionX, file);

Related

Why does the measurement of the size of a file differ from the size of the string that contains it once buffered?

In order to write the content of a file in a buffer, I first need to know the size of the string to allocate. To do this, I use the following function:
long file_length(FILE *fp)
{
if (fp == NULL) return -1L;
fseek(fp, 0L, SEEK_END);
const long len = ftell(fp);
rewind(fp);
return len;
}
And I use it as follows to store the contents of my file:
char *file_content(const char *fname)
{
assert(access(fname, F_OK) != -1);
assert(access(fname, R_OK) != -1);
FILE *fp = fopen(fname, "r");
assert(fp != NULL);
const long flen = file_length(fp);
printf("Length of file: %ld\n", flen);
char *buff = malloc(flen + 1);
assert(buff != NULL);
fread(buff, sizeof(char), flen, fp);
buff[flen + 1] = '\0';
fclose(fp);
return buff;
}
And then I test:
int main()
{
char *content = file_content("test.txt");
printf("Length of buffer: %lld\n", strlen(content));
free(content);
return 0;
}
Here's test.txt:
Hello, world!
This is a simple test.
Stackoverflow.
My program then displays this:
Length of file: 57
Length of buffer: 53
As the file has 4 line feeds, I imagine that the result is related to their interpretation according to the different readings that are made (for the position of the file, with fseek, and for its buffering, with fread). But is it? Or maybe it changes depending on the platform or a reading mode?
If that's the case, so I would like to know how to get the same results, so that I can allocate the exact size of the string directly from my file_length function, without having to subtract the number of line feeds the file contains (if it's possible?) in order to be as optimal as possible.

Copying file pointer into array

Here, I am trying to read from a text file, copy this file into an array, then I want to write the array to another text file. This is not copying into the array at all. I am just getting blank values when I print.
int main(void)
{
char char_array[50];
char copied_array[50];
//int n = 2;
FILE* fpointer = fopen("hello_world.txt", "r");
FILE* fpointer2 = fopen("copyhello.txt", "w");
for(int i = 0;i < 50; i++)
{
fread(&char_array, sizeof(char), 1, fpointer);
copied_array[i] = char_array[i];
}
for(int j = 0;j < 50; j++)
{
printf("char_array: %c\n", copied_array[j]);
}
fclose(fpointer);
fclose(fpointer2);
}
working code. hope this becomes clearer :)
Note you're using fread/fwrite - compare with fgets/fputs for strings.
#include "stdio.h"
#include "string.h"
#define BUFSIZE 50
// memory size 'plus one' to leave room for a string-terminating '\0'
#define BUFMEMSIZE (BUFSIZE+1)
const char *file1 = "hello_world.txt";
const char *file2 = "copyhello.txt";
int main(void)
{
char char_array[BUFMEMSIZE];
char copied_array[BUFMEMSIZE];
FILE *fInput, *fOutput;
fInput = fopen(file1, "r");
if(fInput != NULL)
{
fOutput = fopen(file2, "w");
if(fOutput != NULL)
{
// make sure memory is wiped before use
memset(char_array, 0, BUFMEMSIZE);
memset(copied_array, 0, BUFMEMSIZE);
size_t lastSuccessfulRead = 0;
// the read-then-loop pattern: try and read 50 chars
size_t bytesRead = fread(char_array, sizeof(char), BUFSIZE, fInput);
while(bytesRead != 0)
{
// we got at least 1 char ..
// (to be used at end - so we know where in char_array is the last byte read)
lastSuccessfulRead = bytesRead;
// 'bytesRead' bytes were read : copy to other array
strncpy(copied_array, char_array, bytesRead);
// write to output file, number of bytes read
fwrite(copied_array, sizeof(char), bytesRead, fOutput);
// read more, and loop, see if we got any more chars
bytesRead = fread(char_array, sizeof(char), BUFSIZE, fInput);
}
// set char after the last-read-in char to null, as a string-terminator.
char_array[lastSuccessfulRead] = '\0';
// an array of chars is also a 'string'
printf("char_array: %s\n", char_array);
fclose(fOutput);
}
else printf("cant open %s\n", file2);
fclose(fInput);
}
else printf("cant open %s\n", file1);
}

Unclear reading file in C

I tried cyclically read file in buffer of 100 byte.
When i read file first time - buffer was full. Returned value is 0. No error and no eof (functions "ferror" and "feof" shows no error). Then i tried read file second time and again returned value is 0, no error and no eof. But then i have empty buffer. I don't know what is the problem?
if(fopen_s(&file_in, argv[1], "rb") == 0){
printf("File was opened.\n");
while(!feof(file_in)){
read_code = fread_s(file_data, 100, sizeof(unsigned char), 100, file_in);
if(ferror(file_in)) {
printf("Error!\n");
}
if(feof(file_in)) {
printf("Eof!\n");
}
printf("Read result: %d\n", read_code);
/*Using the buffer*/
memset(file_data, 0, 100);
}
fclose(file_in);
}
For the reasons given in comments regarding fopen_s, et. al., Here is an alternative implementation of reading a binary file using getc(), along with fopen(), fclose(), etc. (I am not using a Microsoft implementation, but am using ANSI C99)
It has a commented section I used to create a test binary file. Other than that it sizes the file you are reading so you can allocate the right amount of memory, then reads the binary data into a buffer.
For navigating your file, take a look at fseek() with its stdio.h defined arguments:
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
In this example, everything is closed or freed before exiting:
#include <windows.h>
#include <ansi_c.h>
long int getFileSizeFromPath(char * path)
{
FILE * file;
long int fileSizeBytes = 0;
file = fopen(path,"r");
if(file){
fseek(file, 0, SEEK_END);
fileSizeBytes = ftell(file);
fseek(file, 0, SEEK_SET);
fclose(file);
}
return fileSizeBytes;
}
int main(int argc, char *argv[])
{
FILE *fp=0;
char *binBuf;
long int size=0;
int i=0;
int byte=0;
//create 100 byte test file (c:\\dev\\tessst.bin)
// fp = fopen(argv[1], "wb");
//
// srand(clock());
// for(i=0;i<100;i++)
// {
// byte = rand();
// putc(byte, fp);
// }
// putc(EOF, fp);
//
// fclose(fp);
size = getFileSizeFromPath(argv[1]);
binBuf = calloc(size + 1, sizeof(char));
fp = fopen(argv[1], "rb");
byte = getc(fp);
while(byte != EOF)
{
binBuf[i++] = (char)byte;
byte = getc(fp);
}
fclose(fp);
free(binBuf);
return 0;
}

Read the entire contents of a file to c char *, including new lines

I'm looking for a cross platform (Windows + Linux) solution to reading the contents of an entire file into a char *.
This is what I've got now:
FILE *stream;
char *contents;
fileSize = 0;
//Open the stream
stream = fopen(argv[1], "r");
//Steak to the end of the file to determine the file size
fseek(stream, 0L, SEEK_END);
fileSize = ftell(stream);
fseek(stream, 0L, SEEK_SET);
//Allocate enough memory (should I add 1 for the \0?)
contents = (char *)malloc(fileSize);
//Read the file
fscanf(stream, "%s", contents);
//Print it again for debugging
printf("Read %s\n", contents);
Unfortunately this will only print the first line in the file so I assume that fscanf stops at the first newline character. However I would like to read the entire file including, and preserving, the new line characters. I'd prefer not to use a while loop and realloc to manually construct the entire string, I mean there has to be a simpler way?
Something like this, may be?
FILE *stream;
char *contents;
fileSize = 0;
//Open the stream. Note "b" to avoid DOS/UNIX new line conversion.
stream = fopen(argv[1], "rb");
//Seek to the end of the file to determine the file size
fseek(stream, 0L, SEEK_END);
fileSize = ftell(stream);
fseek(stream, 0L, SEEK_SET);
//Allocate enough memory (add 1 for the \0, since fread won't add it)
contents = malloc(fileSize+1);
//Read the file
size_t size=fread(contents,1,fileSize,stream);
contents[size]=0; // Add terminating zero.
//Print it again for debugging
printf("Read %s\n", contents);
//Close the file
fclose(stream);
free(contents);
The function fread will read from the stream and not terminate on end-of-line characters.
From the man page, you have:
size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
which reads in nitems of size size.
fread reads all the files as-is:
if (fread(contents, 1, fileSize, stream) != fileSize) {
/* error occurred */
}
I've got this:
ssize_t filetomem(const char *filename, uint8_t **result)
{
ssize_t size = 0;
FILE *f = fopen(filename, "r");
if (f == NULL)
{
*result = NULL;
return -1;
}
fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, 0, SEEK_SET);
*result = malloc(size);
if (size != fread(*result, sizeof(**result), size, f))
{
free(*result);
return -2;
}
fclose(f);
return size;
}
Meaning of return value:
Positive or 0: successfully read the file
minus one: couldn't open file (possibly no such file)
minus two: fread() failed

How to read all contents of file, including NUL chars between valid text?

I have a file that I need to read into a buffer (char *) but the problem is that the file has some "funny characters" in it inbetween the valid text.
So when I write some code like the following:
FILE *fp;
if((fp = fopen(".\\test.txt", "rt"))==NULL){
printf("Cannot open file2\n");
}
fseek(fp, 0, SEEK_END);
long int fsize = ftell(fp);
rewind(fp);
//char *buffer2 = malloc(fsize * sizeof(char));
buffer = malloc(fsize * sizeof(char));
fread(buffer, 1, fsize, fp);
buffer[fsize] = '\0';
fclose(fp);
printf("fsize = %i\n", fsize);
printf("Buffer = %s\n", buffer);
It only prints out the first part of the text file like follows:
Buffer = header
And obviously stops at the first NUL char.
Is thier any way to read the entire buffer of the file, including funny chars?
Or is this not possible in C?
The FSIZE is read correctly, just the FREAD does not read the entire buffer ;-(
Any help would be greatly appreciated ;-)
Thanks
Lynton
UPDATE: OK, I was being a little stupid.....if I write the buffer to a file it has everything in it, only if I write it out to the screen does it stop at the null so that is fine.
Don't open the file in "text" mode ("rt"), use binary mode instead ("rb").
Also, it might well be reading the data, but the printf("Buffer = %s\n", buffer) will only print up to the first NUL, so your debug is not going to do what your want. You probably want to write a little hex dumping function.
How to read all contents of file, including NUL chars between valid text?
Errors:
Allocate enough space if attempting to make a string. OP's code is 1 short. This is a dubious goal if data read may include null chracters.
Open in binary mode #Lawrence Dol
Some more error checking is useful.
// FILE *fp = fopen(".\\test.txt", "rt");
FILE *fp = fopen(".\\test.txt", "rb");
if (fp==NULL) {
printf("Cannot open file2\n");
exit(-1);
}
if (fseek(fp, 0, SEEK_END)) {
printf("fseek() trouble\n");
exit(-1);
}
long fsize = ftell(fp);
if (fsize == -1 || fsize >= SIZE_MAX) {
printf("fell() trouble\n");
exit(-1);
}
// Add 1 if trying to make a string.
size_t sz = (size_t) fsize;
if (making_a_string) sz++;
rewind(fp);
char *buffer = malloc(sizeof *buffer * sz);
if (buffer == NULL && sz > 0) { // Tolerate a file size of 0
printf("malloc() trouble\n");
exit(-1);
}
size_t in = fread(buffer, 1, fsize, fp);
fclose(fp);
if (in != fsize) {
printf("fread() trouble\n");
exit(-1);
}
if (making_a_string) {
buffer[fsize] = '\0';
}
To print the entire data, use, fwrite(). In order to print a character array, a trailing null chracter is not needed as in a string, but the length of the character array is used.
printf("fsize = %ld\n", fsize); // Note: %ld
printf("Buffer = <", );
fwrite(buffer, 1, fsize, stdout);
printf(">\n");

Resources