Unclear reading file in C - 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;
}

Related

How to overwrite a file in C?

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

convert unsigned int to char alphabets

I have the following code that converts a stream data of 16-bit integer to unsigned 8-bit integer.
I am looking to convert them to alphabetical data values and see what they contain.
#include<stdio.h>
int main() {
FILE *fp,*out;
char buffer[256];
size_t i = 0;
fp=fopen("c:/Gosam/input.txt", "rb");
if(fp != 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);
}
The following is the form of my output:
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 50
4294966993 4294966974 4294967019 4294967007
This are the values I want to convert to alphabetical characters and see their content.
I don't know what you expect as an answer (you didn't ask a question), but there seems to be one suspicious thing in your code:
char buffer[256];
Here char means signed char. If your code does manipulations on them (like multiplying by 256), it probably doesn't do what you expect (though I can only guess what you expect - your question doesn't mention it).
Try the following:
unsigned char buffer[256];
Also please ask a question (that is, something with a question mark), and give some examples (input, output).
Your basic mistakes were:
after opening the inputfile checking out instead of fp against NULL
fread until eof won't return the number of characters that could be read (I've used fseek and ftell for this purpose)
writing uint values instead of char values to your file
I've fixed them and commented the affected lines appropriate. I also changed the buffer to use dynamic memory allocation instead of static allocation (that's how you can allocate memory for a buffer of a size that is unknown at compile-time). Please try the following code, which will copy all ASCII characters from one file to your output file (which is probably what you meant by 'alphabetical strings'):
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
FILE *fp, *out;
char *buffer = NULL; /* use a pointer for dynamic memory allocation */
size_t i = 0, charCount = 0;
fp = fopen("c:/input.txt", "r"); /*read as ascii - not binary */
if(fp != NULL){ /*use 'fp' here 'out' is not initalized */
fseek(fp, 0, SEEK_END); /* go to end of the file */
charCount = ftell(fp) - 1; /* get position */
fseek(fp, 0, SEEK_SET); /* return to the beginning of the file */
buffer = (char*)malloc(sizeof(char)*charCount); /* allocate memory */
fread(buffer, sizeof(char) * charCount, 1, fp); /* reads all characters from the file */
}
out = fopen("c:/output.txt", "w");
if(out != NULL){
for(i = 0; i < charCount; i += 1){ /* loop from 0 to count of characters */
const unsigned char var = buffer[i];
fprintf(out, "%c", var);
}
fclose(out);
}
fclose(fp);
if(buffer != NULL){
free(buffer); /* deallocate memory */
}
return 0;
}

c code text not displayed

iv'e written a part of a code which basically transfers text from a txt file into a variable and prints it(as a part of a program),yet it does not print the contents at all.
#include <stdio.h>
#include <stdlib.h>
#define WRONG_ARGUMENTS (-1)
int Lines(FILE * file);
int Length(FILE * file);
int Read(FILE * file);
int Lines(FILE * file)
{
int c=0,count=0;
++count;
while(c!=EOF)
{
c=fgetc(file);
if(c=='\n')
++count;
}
return count;
}
int Length(FILE * file)
{
int c,count=0;
while((c=fgetc(file))!=EOF)
{
++count;
}
return count;
}
int Reader(FILE * Text,char * File)
{
int counter=0;
while(fscanf(Text,"%s",File)!=EOF)
{
++counter;
strcat(File," ");
}
return counter;
}
int main(int argc,char * argv[]) {
FILE * Text=NULL;
if(argc!=2)
{
printf("usage:library text dictionary\n");
return -1;
}
Text = fopen(argv[1],"r");
if(Text==NULL)
{
printf("file %s could not be opened\n",argv[1]);
return -1;
}
char * File = "";
File=malloc(Length(Text)*(sizeof(char)));
int r = Reader(Text,File);
printf(File);
return 0;
}
i will be more than glad to understand the problem in the partial code
the output is x>
thanks,
Consider the following cut-down example. You'll notice that the getFileLength function (a) doesn't actually read anything from the file and (b) makes use of the fseek and ftell functions - fseek is the function that you use to reposition the file-pointer when it reaches EOF.
Imagine that you weren't printing the data, but doing something else with it. What if the file is a billion bytes long? We sure don't want to read 1,000,000,000 times from it just to determine its length!
As for the use of calloc - it zero initializes the data it allocates. Since you're reading text, you want to ensure that the text is NULL-terminated. (NULL generally = 0, though I've seen evil macros that change this) This NULL terminator is also why I allocate 1 byte more than the file contains.
#include <stdio.h>
#include <stdlib.h>
long getFileLength(FILE *input)
{
long result;
long origPos = ftell(input);
fseek(input, 0, SEEK_END);
result = ftell(input);
fseek(input, origPos, SEEK_SET);
return result;
}
int main (void)
{
FILE *fp;
long fileLen, numBytesRead;
char *data;
fp = fopen("main.cpp", "rb");
fileLen = getFileLength(fp);
data = (char*)calloc(sizeof(char), fileLen+1);
numBytesRead = fread(data, sizeof(char), fileLen, fp);
if (numBytesRead != fileLen)
printf("Error reading all bytes from file. Expected: %d, Read %d\n", fileLen, numBytesRead);
else
printf("%s", data);
free(data);
fclose(fp);
}

Creating copy of binary file from hex representation of it

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.

How to read the content of a file to a string in C?

What is the simplest way (least error-prone, least lines of code, however you want to interpret it) to open a file in C and read its contents into a string (char*, char[], whatever)?
I tend to just load the entire buffer as a raw memory chunk into memory and do the parsing on my own. That way I have best control over what the standard lib does on multiple platforms.
This is a stub I use for this. you may also want to check the error-codes for fseek, ftell and fread. (omitted for clarity).
char * buffer = 0;
long length;
FILE * f = fopen (filename, "rb");
if (f)
{
fseek (f, 0, SEEK_END);
length = ftell (f);
fseek (f, 0, SEEK_SET);
buffer = malloc (length);
if (buffer)
{
fread (buffer, 1, length, f);
}
fclose (f);
}
if (buffer)
{
// start to process your data / extract strings here...
}
Another, unfortunately highly OS-dependent, solution is memory mapping the file. The benefits generally include performance of the read, and reduced memory use as the applications view and operating systems file cache can actually share the physical memory.
POSIX code would look like this:
int fd = open("filename", O_RDONLY);
int len = lseek(fd, 0, SEEK_END);
void *data = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
Windows on the other hand is little more tricky, and unfortunately I don't have a compiler in front of me to test, but the functionality is provided by CreateFileMapping() and MapViewOfFile().
If "read its contents into a string" means that the file does not contain characters with code 0, you can also use getdelim() function, that either accepts a block of memory and reallocates it if necessary, or just allocates the entire buffer for you, and reads the file into it until it encounters a specified delimiter or end of file. Just pass '\0' as the delimiter to read the entire file.
This function is available in the GNU C Library, http://www.gnu.org/software/libc/manual/html_mono/libc.html#index-getdelim-994
The sample code might look as simple as
char* buffer = NULL;
size_t len;
ssize_t bytes_read = getdelim( &buffer, &len, '\0', fp);
if ( bytes_read != -1) {
/* Success, now the entire file is in the buffer */
If you are reading special files like stdin or a pipe, you are not going to be able to use fstat to get the file size beforehand. Also, if you are reading a binary file fgets is going to lose the string size information because of embedded '\0' characters. Best way to read a file then is to use read and realloc:
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main () {
char buf[4096];
ssize_t n;
char *str = NULL;
size_t len = 0;
while (n = read(STDIN_FILENO, buf, sizeof buf)) {
if (n < 0) {
if (errno == EAGAIN)
continue;
perror("read");
break;
}
str = realloc(str, len + n + 1);
memcpy(str + len, buf, n);
len += n;
str[len] = '\0';
}
printf("%.*s\n", len, str);
return 0;
}
Note: This is a modification of the accepted answer above.
Here's a way to do it, complete with error checking.
I've added a size checker to quit when file was bigger than 1 GiB. I did this because the program puts the whole file into a string which may use too much ram and crash a computer. However, if you don't care about that you could just remove it from the code.
#include <stdio.h>
#include <stdlib.h>
#define FILE_OK 0
#define FILE_NOT_EXIST 1
#define FILE_TOO_LARGE 2
#define FILE_READ_ERROR 3
char * c_read_file(const char * f_name, int * err, size_t * f_size) {
char * buffer;
size_t length;
FILE * f = fopen(f_name, "rb");
size_t read_length;
if (f) {
fseek(f, 0, SEEK_END);
length = ftell(f);
fseek(f, 0, SEEK_SET);
// 1 GiB; best not to load a whole large file in one string
if (length > 1073741824) {
*err = FILE_TOO_LARGE;
return NULL;
}
buffer = (char *)malloc(length + 1);
if (length) {
read_length = fread(buffer, 1, length, f);
if (length != read_length) {
free(buffer);
*err = FILE_READ_ERROR;
return NULL;
}
}
fclose(f);
*err = FILE_OK;
buffer[length] = '\0';
*f_size = length;
}
else {
*err = FILE_NOT_EXIST;
return NULL;
}
return buffer;
}
And to check for errors:
int err;
size_t f_size;
char * f_data;
f_data = c_read_file("test.txt", &err, &f_size);
if (err) {
// process error
}
else {
// process data
free(f_data);
}
What is the simplest way (least error-prone, least lines of code, however you want to interpret it) to open a file in C and read its contents into a string ...?
Sadly, even after years, answers are error prone and many lack proper string formation and error checking.
#include <stdio.h>
#include <stdlib.h>
// Read the file into allocated memory.
// Return NULL on error.
char* readfile(FILE *f) {
// f invalid? fseek() fail?
if (f == NULL || fseek(f, 0, SEEK_END)) {
return NULL;
}
long length = ftell(f);
rewind(f);
// Did ftell() fail? Is the length too long?
if (length == -1 || (unsigned long) length >= SIZE_MAX) {
return NULL;
}
// Convert from long to size_t
size_t ulength = (size_t) length;
char *buffer = malloc(ulength + 1);
// Allocation failed? Read incomplete?
if (buffer == NULL || fread(buffer, 1, ulength, f) != ulength) {
free(buffer);
return NULL;
}
buffer[ulength] = '\0'; // Now buffer points to a string
return buffer;
}
Note that if the text file contains null characters, the allocated data will contain all the file data, yet the string will appear to be short. Better code would also return the length information so the caller can handle that.
char* readfile(FILE *f, size_t *ulength_ptr) {
...
if (ulength_ptr) *ulength_ptr == *ulength;
...
}
If the file is text, and you want to get the text line by line, the easiest way is to use fgets().
char buffer[100];
FILE *fp = fopen("filename", "r"); // do not use "rb"
while (fgets(buffer, sizeof(buffer), fp)) {
... do something
}
fclose(fp);
If you're using glib, then you can use g_file_get_contents;
gchar *contents;
GError *err = NULL;
g_file_get_contents ("foo.txt", &contents, NULL, &err);
g_assert ((contents == NULL && err != NULL) || (contents != NULL && err == NULL));
if (err != NULL)
{
// Report error to user, and free error
g_assert (contents == NULL);
fprintf (stderr, "Unable to read file: %s\n", err->message);
g_error_free (err);
}
else
{
// Use file contents
g_assert (contents != NULL);
}
}
Just modified from the accepted answer above.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
char *readFile(char *filename) {
FILE *f = fopen(filename, "rt");
assert(f);
fseek(f, 0, SEEK_END);
long length = ftell(f);
fseek(f, 0, SEEK_SET);
char *buffer = (char *) malloc(length + 1);
buffer[length] = '\0';
fread(buffer, 1, length, f);
fclose(f);
return buffer;
}
int main() {
char *content = readFile("../hello.txt");
printf("%s", content);
}
// Assumes the file exists and will seg. fault otherwise.
const GLchar *load_shader_source(char *filename) {
FILE *file = fopen(filename, "r"); // open
fseek(file, 0L, SEEK_END); // find the end
size_t size = ftell(file); // get the size in bytes
GLchar *shaderSource = calloc(1, size); // allocate enough bytes
rewind(file); // go back to file beginning
fread(shaderSource, size, sizeof(char), file); // read each char into ourblock
fclose(file); // close the stream
return shaderSource;
}
This is a pretty crude solution because nothing is checked against null.
I will add my own version, based on the answers here, just for reference. My code takes into consideration sizeof(char) and adds a few comments to it.
// Open the file in read mode.
FILE *file = fopen(file_name, "r");
// Check if there was an error.
if (file == NULL) {
fprintf(stderr, "Error: Can't open file '%s'.", file_name);
exit(EXIT_FAILURE);
}
// Get the file length
fseek(file, 0, SEEK_END);
long length = ftell(file);
fseek(file, 0, SEEK_SET);
// Create the string for the file contents.
char *buffer = malloc(sizeof(char) * (length + 1));
buffer[length] = '\0';
// Set the contents of the string.
fread(buffer, sizeof(char), length, file);
// Close the file.
fclose(file);
// Do something with the data.
// ...
// Free the allocated string space.
free(buffer);
easy and neat(assuming contents in the file are less than 10000):
void read_whole_file(char fileName[1000], char buffer[10000])
{
FILE * file = fopen(fileName, "r");
if(file == NULL)
{
puts("File not found");
exit(1);
}
char c;
int idx=0;
while (fscanf(file , "%c" ,&c) == 1)
{
buffer[idx] = c;
idx++;
}
buffer[idx] = 0;
}

Resources