My question is very simple. I have a file of ascii or binary , whatever. Now, I want every byte in the file to be 0x4f, how can I do it in C ? The question is so simple, but suprisingly, there is no answer on the Internet. I have a sample code, however, there is a dead loop when I run the program:
#include <stdio.h>
int main ()
{
FILE * pFile;
pFile = fopen ("write_file_2","wb");
unsigned char c = 0x4f;
while(1){
if( feof(pFile) )
break;
int res = fputc(c, pFile);
printf("%d\n", res);
}
fclose (pFile);
return 0;
}
I wonder why the feof() takes no effect.
Thanks!
The problem is that you are using "wb" (w - Create an empty file for output operations), change to "rb+", and use ftell instead of feof (take a look to “while( !feof( file ) )” is always wrong)
#include <stdio.h>
int main(void)
{
FILE * pFile;
long i, size;
unsigned char c = 0x4f;
pFile = fopen("write_file_2", "rb+");
fseek(pFile, 0, SEEK_END);
size = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
for (i = 0; i < size; i++) {
int res = fputc(c, pFile);
printf("%d\n", res);
}
fclose(pFile);
return 0;
}
As soon as you do this pFile = fopen ("write_file_2","wb"); the file is opened and truncated to 0 bytes. So the pFile is at EOF so feof() will return true.
You may want to open it with "r+b", get the size using ftell(), fseek() to 0th position and start writing design data.
Maybe you should firstly check the size of the file :
fseek(f, 0, SEEK_END);
lSize = ftell(f);
fseek(f, 0, SEEK_SET);
Then use 'fwrite' to write desired bytes and number of bytes into the file
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last year.
Improve this question
int read_last_ints(const char *file_name, int num_ints)
{
FILE *fp = fopen(file_name, "r");
if (fp == NULL)
{
return 1;
}
int integers;
long int size;
size_t nread;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
rewind(fp);
size = size - num_ints;
fseek(fp, size, SEEK_SET);
while ((nread = fread(&integers, 1, sizeof(int), fp)) > 0)
{
printf("%d\n", integers);
}
fclose(fp);
return 0;
}
I am trying to create a function that reads the last integers from a binary file, however my code doesn't work as intended. When I try to test my code, it produces random numbers that don't make sence. If anyone has any advice, please share it. Thank you.
You need to position backwards from the end of the file by the size of num_ints integers.
A minimalist change to your code is:
int read_last_ints(const char *file_name, int num_ints)
{
FILE *fp = fopen(file_name, "r");
if (fp == NULL)
{
return 1;
}
int integers;
long int size;
size_t nread;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
rewind(fp);
size = size - sizeof(int) * num_ints; /* MNC — minimum necessary change */
fseek(fp, size, SEEK_SET);
while ((nread = fread(&integers, 1, sizeof(int), fp)) > 0)
{
printf("%d\n", integers);
}
fclose(fp);
return 0;
}
However, you can make use of the SEEK_END option more effectively. You should probably also use "rb" instead of "r" to read a binary file. Using "rb" is crucial on Windows; it is harmless on Unix-like systems (because the C standard mandates support for "rb", even though it is not necessary on Unix). This code also renames the variable integers to the singular integer.
int read_last_ints(const char *file_name, int num_ints)
{
FILE *fp = fopen(file_name, "r");
if (fp == NULL)
{
return 1;
}
int integer;
size_t nread;
fseek(fp, -(long)(num_ints * sizeof(int)), SEEK_END);
while ((nread = fread(&integer, 1, sizeof(int), fp)) > 0)
{
printf("%d\n", integer);
}
fclose(fp);
return 0;
}
This saves a call to fseek(), ftell() and rewind(). The rewind() was always superfluous, but you don't need to know the actual size of the file. The fseek() call simply seeks to the relevant number of bytes before the end of the file. You'd only have problems if the file is not big enough to hold that many integers (and it would just do its best, seeking to the start and reading as much as possible).
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.
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;
}
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
I'd like to make copy of my binary file, but I need to make it from hex representation of my binary file.
In the first program I create txt file with with hex representation of my binary file:
#include <stdio.h>
#include <stdlib.h>
const int BYTE = 1;
int counter = 0;
int read;
long size;
FILE *file1 = NULL;
FILE *file2 = NULL;
fpos_t length;
int main() {
unsigned char hex[3];
unsigned char buffer[1];
file1 = fopen("server.pdf", "rb");
fseek(file1, 0, SEEK_END);
fgetpos(file1, &length);
size = length.__pos;
fseek(file1, 0, SEEK_SET);
if (file1) {
file2 = fopen("test.txt", "w");
while (counter < size) {
read = fread(buffer, 1, BYTE, file1);
counter += read;
i = 0;
while(i<read) {
sprintf(hex, "%02x", (unsigned int) buffer[i++]);
fwrite(hex, 1, BYTE, file2);
}
}
} else
printf("ERROR");
fclose(file1);
fclose(file2);
}
In the second, I read data from txt file and after that I write it to binary file:
#include <stdio.h>
FILE *file1;
FILE *file2;
int size;
fpos_t length;
int main(){
file1 = fopen("test.txt", "r");
fseek(file1, 0, SEEK_END);
fgetpos(file1, &length);
size = length.__pos;
fseek(file1, 0, SEEK_SET);
char buffer[1];
char hex[3];
int counter = 0;
int read;
if(file1){
file2 = fopen("test.pdf", "wb");
while (counter < size) {
read = fread(hex, 1, 3, file1);
counter += read;
sscanf(hex, "%02x", buffer);
fwrite(buffer, 1, 1, file2);
}
}
fclose(file1);
fclose(file2);
}
Unfortunately I can't open my copy. What is the reason?
Have you looked at the files content? You wont be able to sprintf the hex representation to the variable hex since it's 1 byte in size.
The variable hex is declared hex[BYTE] where BYTE = 1, but your sprintf format string looks like this: "%02x" ie 2 bytes, then you need room for a terminating zero.
The same goes for when you write to the file, you only write 1 byte from your hex string.
Declaring a variable as: var[1] is pointless you can achieve the same thing with var btw.
Besides this you should also add proper error handling, if you can not successfully open the file. This means checking the file pointer after your call to fopen, then take an appropriate action. perror() will print an error string that corresponds to errno, and in case of a file that does not exist it will print something like: "no such file or directory" or similar.
When you said you can't open your copy, you mean you have an error in fopen("test.txt", "r")? Did you check errno value? Check perror() and strerror().
Besides, you have no loop in second program.