Allocating memory from a file, then using fread and fwrite C - c

I'm having a bit of trouble getting my code to work, which is to open a file, count the number of characters in it, and then allocating that using malloc(). And then I am supposed to read the characters in from one file (mine contained "Hello World!") using fread(), and write them to a blank .txt file using fwrite.
My code so far is printing corrupted characters. I couldn't find any questions that were specific enough to my problem. If anyone could tell me what I'm doing wrong I'd appreciate it. I think it is specific to my fread and fwrite calls, but nothing I've tried works.
The code in question (not commented yet, sorry!):
#include <stdio.h>
#include <stdlib.h>
//initialized using ./a.out in.txt out.txt
int main(int argc, char *argv[])
{
FILE *fp;
int count, end;
char *memory;
char c[64];
fp = fopen(argv[1], "r");
if((fp) == NULL)
{
printf("Error: cannot open file.\n");
}
else
{
while((fgetc(fp))!= EOF)
{
count++;
}
memory = (char*)malloc(count);
c[64] = fread(memory, sizeof(char), 1, fp);
fclose(fp);
fp = fopen(argv[2], "w");
fwrite(c, sizeof(char), sizeof(c), fp);
fclose(fp);
free(memory);
}
return 0;
}

code have logical mistakes, as follow
Initialise variables int count= 0 , char c[64]= {0};
Type cast not required memory = malloc(count);
First you have counted number of char in file so Before reading again file rewind it by fseek(fp,0,SEEK_SET);
c[64] = fread(memory, sizeof(char), 1, fp); In this if you are reading single char, you should read complete file , To read complete file do fread(memory, 1, count, fp); and c[64] is out of bound and fread return the number of char successfully read .
fwrite(c, sizeof(char), sizeof(c), fp); In this you are writing complete char array to file but you have read only single variable in array which number of char read . So you are writing uninitialised char array to file. so you are getting corrupted character in file.
To write in file do fwrite(memory, 1, count, fp);
To solve problem ,avoid above error and read complete file in char array and then write.

Alright, there are a number of problems here, I'll start with the least bad:
memory = (char*)malloc(count);
Casting the return of malloc() is unnecessary and can potentially mask errors, for more info see here.
int count;
You never initialise count to anything. This is undefined behaviour and there is no guarantee it'll start at 0. It can start at random garbage left in memory. Same for end
c[64] = fread(memory, sizeof(char), 1, fp);
2 Problems here. c[64] is out of bounds for the array c since indexes start at 0, so the last element in the array is c[63]. sizeof(char) is defined to be 1, so use 1 instead. Further, fread() returns the amount of characters read, so not sure what you are trying to do with that value even.
fwrite(c, sizeof(char), sizeof(c), fp);
You're writing a complete uninitialised array to the file (=garbage)

Related

How to read a complete file with scanf maybe something like %[^\EOF] without loop in single statement

I want to know if I can read a complete file with single scanf statement. I read it with below code.
#include<stdio.h>
int main()
{
FILE * fp;
char arr[200],fmt[6]="%[^";
fp = fopen("testPrintf.c","r");
fmt[3] = EOF;
fmt[4] = ']';
fmt[5] = '\0';
fscanf(fp,fmt,arr);
printf("%s",arr);
printf("%d",EOF);
return 0;
}
And it resulted into a statement after everything happened
"* * * stack smashing detected * * *: terminated
Aborted (core dumped)"
Interestingly, printf("%s",arr); worked but printf("%d",EOF); is not showing its output.
Can you let me know what has happened when I tried to read upto EOF with scanf?
If you really, really must (ab)use fscanf() into reading the file, then this outlines how you could do it:
open the file
use fseek() and
ftell() to find the size of the file
rewind() (or fseek(fp, 0, SEEK_SET)) to reset the file to the start
allocate a big buffer
create a format string that reads the correct number of bytes into the buffer and records how many characters are read
use the format with fscanf()
add a null terminating byte in the space reserved for it
print the file contents as a big string.
If there are no null bytes in the file, you'll see the file contents printed. If there are null bytes in the file, you'll see the file contents up to the first null byte.
I chose the anodyne name data for the file to be read — there are endless ways you can make that selectable at runtime.
There are a few assumptions made about the size of the file (primarily that the size isn't bigger than can be fitted into a long with signed overflow, and that it isn't empty). It uses the fact that the %c format can accept a length, just like most of the formats can, and it doesn't add a null terminator at the end of the string it reads and it doesn't fuss about whether the characters read are null bytes or anything else — it just reads them. It also uses the fact that you can specify the size of the variable to hold the offset with the %n (or, in this case, the %ln) conversion specification. And finally, it assumes that the file is not shrinking (it will ignore growth if it is growing), and that it is a seekable file, not a FIFO or some other special file type that does not support seeking.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const char filename[] = "data";
FILE *fp = fopen(filename, "r");
if (fp == NULL)
{
fprintf(stderr, "Failed to open file %s for reading\n", filename);
exit(EXIT_FAILURE);
}
fseek(fp, 0, SEEK_END);
long length = ftell(fp);
rewind(fp);
char *buffer = malloc(length + 1);
if (buffer == NULL)
{
fprintf(stderr, "Failed to allocate %ld bytes\n", length + 1);
exit(EXIT_FAILURE);
}
char format[32];
snprintf(format, sizeof(format), "%%%ldc%%ln", length);
long nbytes = 0;
if (fscanf(fp, format, buffer, &nbytes) != 1 || nbytes != length)
{
fprintf(stderr, "Failed to read %ld bytes (got %ld)\n", length, nbytes);
exit(EXIT_FAILURE);
}
buffer[length] = '\0';
printf("<<<SOF>>\n%s\n<<EOF>>\n", buffer);
free(buffer);
return(0);
}
This is still an abuse of fscanf() — it would be better to use fread():
if (fread(buffer, sizeof(char), length, fp) != (size_t)length)
{
fprintf(stderr, "Failed to read %ld bytes\n", length);
exit(EXIT_FAILURE);
}
You can then omit the variable format and the code that sets it, and also nbytes. Or you can keep nbytes (maybe as a size_t instead of long) and assign the result of fread() to it, and use the value in the error report, along the lines of the test in the fscanf() variant.
You might get warnings from GCC about a non-literal format string for fscanf(). It's correct, but this isn't dangerous because the programmer is completely in charge of the content of the format string.

Difference between specifications of fread and fgets?

What is the difference between fread and fgets when reading in from a file?
I use the same fwrite statement, however when I use fgets to read in a .txt file it works as intended, but when I use fread() it does not.
I've switched from fgets/fputs to fread/fwrite when reading from and to a file. I've used fopen(rb/wb) to read in binary rather than standard characters. I understand that fread will get /0 Null bytes as well rather than just single lines.
//while (fgets(buff,1023,fpinput) != NULL) //read in from file
while (fread(buff, 1, 1023, fpinput) != 0) // read from file
I expect to read in from a file to a buffer, put the buffer in shared memory, and then have another process read from shared memory and write to a new file.
When I use fgets() it works as intended with .txt files, but when using fread it adds a single line from 300~ characters into the buffer with a new line. Can't for the life of me figure out why.
fgets will stop when encountering a newline. fread does not. So fgets is typically only useful for text files, while fread can be used for both text and binary files.
From the C11 standard:
7.21.7.2 The fgets function
The fgets function reads at most one less than the number of characters specified by n from the stream pointed to by stream into the array pointed to by s. No additional characters are read after a new-line character (which is retained) or after end-of-file. A null character is written immediately after the last character read into the array.
7.21.8.1 The fread function
The fread function reads, into the array pointed to by ptr, up to nmemb elements whose size is specified by size, from the stream pointed to by stream. For each object, size calls are made to the fgetc function and the results stored, in the order read, in an array of unsigned char exactly overlaying the object. The file position indicator for the stream (if defined) is advanced by the number of characters successfully read. If an error occurs, the resulting value of the file position indicator for the stream is indeterminate. If a partial element is read, its value is indeterminate.
This snippet maybe will make things clearer for you. It just copies a file in chunks.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char ** argv)
{
if(argc != 3) {
printf("Usage: ./a.out src dst\n");
printf("Copies file src to dst\n");
exit(EXIT_SUCCESS);
}
const size_t chunk_size = 1024;
FILE *in, *out;
if(! (in = fopen(argv[1], "rb"))) exit(EXIT_FAILURE);
if(! (out = fopen(argv[2], "wb"))) exit(EXIT_FAILURE);
char * buffer;
if(! (buffer = malloc(chunk_size))) exit(EXIT_FAILURE);
size_t bytes_read;
do {
// fread returns the number of successfully read elements
bytes_read = fread(buffer, 1, chunk_size, in);
/* Insert any modifications you may */
/* want to do here */
// write bytes_read bytes from buffer to output file
if(fwrite(buffer, 1, bytes_read, out) != bytes_read) exit(EXIT_FAILURE);
// When we read less than chunk_size we are either done or an error has
// occured. This error is not handled in this program.
} while(bytes_read == chunk_size);
free(buffer);
fclose(out);
fclose(in);
}
You mentioned in a comment below that you wanted to use this for byteswapping. Well, you can just use the following snippet. Just insert it where indicated in code above.
for(int i=0; i < bytes_read - bytes_read%2; i+=2) {
char tmp = buffer[i];
buffer[i] = buffer[i+1];
buffer[i+1] = tmp;
}

create a binary file in C

I'm currently working on a binary file creation. Here is what I have tried.
Example 1:
#include<stdio.h>
int main() {
/* Create the file */
int a = 5;
FILE *fp = fopen ("file.bin", "wb");
if (fp == NULL)
return -1;
fwrite (&a, sizeof (a), 1, fp);
fclose (fp);
}
return 0;
}
Example 2:
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
char str[256] = {'\0'};
strcpy(str, "3aae71a74243fb7a2bb9b594c9ea3ab4");
fp = fopen("file.bin", "wb");
if(fp == NULL)
return -1;
fwrite(str, sizeof str, 1, fp);
return 0;
}
Example 1 gives the right output in binary form. But Example 2 where I'm passing string doesn't give me right output. It writes the input string which I have given into the file and appends some data(binary form).
I don't understand and I'm unable to figure it out what mistake I'm doing.
The problem is that sizeof str is 256, that is, the entire size of the locally declared character array. However, the data you are storing in it does not require all 256 characters. The result is that the write operation writes all the characters of the string plus whatever garbage happened to be in the character array already. Try the following line as a fix:
fwrite(str, strlen(str), 1, fp);
C strings are null terminated, meaning that anything after the '\0' character must be ignored. If you read the file written by Example 2 into a str[256] and print it out using printf("%s", str), you would get the original string back with no extra characters, because null terminator would be read into the buffer as well, providing proper termination for the string.
The reason you get the extra "garbage" in the output is that fwrite does not interpret str[] array as a C string. It interprets it as a buffer of size 256. Text editors do not interpret null character as a terminator, so random characters from str get written to the file.
If you want the string written to the file to end at the last valid character, use strlen(str) for the size in the call of fwrite.

Why the output the program is something different?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fp;
char ch;
char buffer[80] ;
fp = fopen("c:\\Rasmi Personal\\hello.txt", "w");
if(fp == NULL)
{
printf("File not found");
exit(1);
}
else
{
while(1)
{
gets(buffer);
fwrite(buffer, strlen(buffer), 2, fp); /* I made, size_t nitems = 2 (third element/argument)*/
fwrite("\n", 1, 1, fp);
}
}
fclose(fp);
return 0;
}
Input:
Rasmi Ranjan Nayak
Output:
Rasmi Ranjan Nayak 0# ÿ" 8ÿ"
Why this garbage is coming.
According to fwrite() function. if the size_t nitems is more than 1 then the entered text will be written more than once.
But here why I am getting garbage?
You're telling fwrite() to write two times strlen(buffer) bytes from the buffer (by setting nmemb = 2 you're making it write two "objects", each of which is strlen(buffer) bytes long), so it reads twice the number of bytes that are actually present.
The "garbage" is simply whatever happens to appear in memory after the string ends in buffer.
This is broken code, nmemb should be 1.
The signature of fwrite function is
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
ptr
Pointer to the array of elements to be written.
size
Size in bytes of each element to be written.
count
Number of elements, each one with a size of size bytes.
stream
Pointer to a FILE object that specifies an output stream.
In this case, if you try to write count * size who is bigger (in bytes) than the original string you have this garbage. If you clean the buffer
memset(buffer,0,80*sizeof(char));
gets(buffer);
probably will see a different result
$ ./a.out
asdadsadasdsad
$ cat -v hello.txt
asdadsadasdsad^#^#^#^#^#^#^#^#^#^#^#^#^#^#
but the text is always writen once. the difference is how many bytes will be writen

fread() puts weird things into char array

I have a file that I want to be read from and printed out to the screen. I'm using XCode as my IDE. Here is my code...
fp=fopen(x, "r");
char content[102];
fread(content, 1, 100, fp);
printf("%s\n", content);
The content of the file is "Bacon!" What it prints out is \254\226\325k\254\226\234.
I have Googled all over for this answer, but the documentation for file I/O in C seems to be sparse, and what little there is is not very clear. (To me at least...)
EDIT: I switched to just reading, not appending and reading, and switched the two middle arguments in fread(). Now it prints out Bacon!\320H\320 What do these things mean? Things as in backslash number number number or letter. I also switched the way to print it out as suggested.
You are opening the file for appending and reading. You should be opening it for reading, or moving your read pointer to the place from which you are going to read (the beginning, I assume).
FILE *fp = fopen(x, "r");
or
FILE *fp = fopen(x, "a+");
rewind(fp);
Also, fread(...) does not zero-terminate your string, so you should terminate it before printing:
size_t len = fread(content, 1, 100, fp);
content[len] = '\0';
printf("%s\n", content);
I suppose, you meant this:
printf("%s\n", content);
Maybe:
fp = fopen(x, "a+");
if(fp)
{
char content[102];
memset(content, 0 , 102);
// arguments are swapped.
// See : http://www.cplusplus.com/reference/clibrary/cstdio/fread/
// You want to read 1 byte, 100 times
fread(content, 1, 100, fp);
printf("%s\n", content);
}
A possible reason is that you do not terminate the data you read, so printf prints the buffer until it finds a string terminator.

Resources