In my code below, the file is being written correctly as far as I can tell. When I look in the file floats.dat I see this stream of binary ÍÌL#33c#ÍÌÜ#ffFAßOeA^#^#bBf6zE33äCff<83>BÍ̦B
However my program always ends up triggering this if statement:
if(fread(inputFloats, sizeof(float), LENGTH, binaryFile) < LENGTH)
{
fprintf(stderr, "Problem reading some or all data from %s\n\n", binaryFileName);
return EXIT_FAILURE;
}
Does anybody see something I've done wrong here? Full code below.
#include <stdlib.h>
#include <stdio.h>
#define LENGTH 10
int main(void)
{
FILE *binaryFile, *textFile;
char *binaryFileName = "floats.dat", *textFileName = "floats.txt";
float floats[LENGTH] = {3.2, 3.55, 6.9, 12.4, 14.332, 56.5, 4003.4, 456.4, 65.7, 83.4};
float inputFloats[LENGTH];
int i;
if((binaryFile = fopen(binaryFileName, "r+")) == NULL)
{
fprintf(stderr, "Problem opening %s", binaryFileName);
}
if(fwrite(floats, sizeof(float), LENGTH, binaryFile) < LENGTH)
{
fprintf(stderr, "Problem writing some or all data to %s\n", binaryFileName);
return EXIT_FAILURE;
}
printf("DATA WRITTEN SUCCESSFULLY\n");
if(fread(inputFloats, sizeof(float), LENGTH, binaryFile) < LENGTH)
{
fprintf(stderr, "Problem reading some or all data from %s\n\n", binaryFileName);
return EXIT_FAILURE;
}
for(i = 0; i < LENGTH; i++)
{
printf("float[%d] = %f\n", i, floats[i]);
}
return EXIT_SUCCESS;
}
You're not working with text data so you should specify a binary mode when opening the file. Use r+b instead of r+
You need to fseek(binaryFile, 0, SEEK_SET) to "rewind" the file after writing. rewind can also be used for this case - fseek allows you to position the read/write pointer wherever you want.
The FILE structure keeps a record of where in the file it is currently pointing. Since you've just written to binaryFile, the file pointer is at the end of what you've written.
You therefore need to rewind the file, using fseek(binaryFile, 0, SEEK_SET); before you read.
You forgot to rewind your file before reading it:
rewind(binaryFile);
When you finish writing to the file, the FILE pointer is at the end of it, so of course if you try reading it will not work. Try using fseek to move the pointer to the beginning of the file before reading.
Please avoid this :
if((binaryFile = fopen(binaryFileName, "r+")) == NULL) {
and prefer this:
binaryFile = fopen(binaryFileName, "rb+");
if(!binaryFile) {
Related
I'm trying to make a program that uses fgets to take the text from a preexisting file, invert it and then write it to another file. This is the code I've written so far:
#include <stdio.h>
#include <string.h>
int main()
{
int c, d;
FILE *file1, *file2;
char string [100], *begin, *end, temp;
file1 = fopen("StartingFile.txt", "rt");
if (file1 == NULL)
{
printf ("Error - Couldn't open file\n");
return (-1);
}
fgets(string, 100, file1);
fclose (file1);
begin = string;
end = begin + strlen(string) - 1;
while (end > begin)
{
temp = *begin;
*begin = *end;
*end = temp;
++begin;
--end;
}
file2 = fopen("FinalFile.txt", "wt");
fprintf (file2, "%s", string);
fclose (file2);
printf ("%s\n", string);
return 0;
}
It works fine if the text in the preexisting file is all in one line, but if it has more than one line, only the first one is inverted and written to the new file. I think that fgets can only read one line, so I think I'll have to use a loop, but I'm having trouble implementing it. Can someone give me a hand? Thanks in advance!
To read each line separately from file use fgets in while loop as below,
while(fgets(string, sizeof(string), file1) != NULL)
{
...
}
fclose(file1);
Inside the loop operate on each line to reverse it.
Your code has quite a few logical errors in it. I would recommend using other f* methods instead.
If you want an easy solution, open the file, determine its length, create two buffers of the size of the file, fill the first buffer with the file's contents and then do a loop to copy the reverse to the other buffer, then write that buffer back. Roughly that would look like this:
#include <stdio.h>
#include <string.h>
int main()
{
FILE *file;
file = fopen("StartingFile.txt", "rt");
if (file == NULL)
{
printf ("Error - Couldn't open file\n");
return (-1);
}
fseek(file, 0, SEEK_END); // move file pointer to end of file
long size = ftell(file); // file pointer position == character count in file
fseek(file, 0, SEEK_SET); // move back to beginning of file
char* buffer = malloc(size * sizeof(char));
fread(buffer, sizeof(char), size, file) // read file contents to buffer
for(long i = 0; i < size/2; ++i)
{
buffer[i] = buffer[size-i-1];
}
fseek(file, 0, SEEK_SET); // The fread set the file pointer to the end so we need to put it to the front again.
fwrite(buffer, sizeof(char), size, file); // Write reverted content
delete buffer;
fclose (file);
}
I haven't tested it and it may contain a few errors since I haven't programmed in C for some time. The only reason to still be programming in C anyways is efficiency and if you want your program to be efficient, the two buffer solution isn't the best either. At least not in terms of memory usage.
I highly recommend getting familiar with all the functions available in C (stdio and so on) cplusplus.com is a great reference for that.
Regards, Xaser
I want to read the data of the file into a string.
Is there a function that reads the whole file into a character array?
I open the file like this:
FILE *fp;
for(i = 0; i < filesToRead; i++)
{
fp = fopen(name, "r");
// Read into a char array.
}
EDIT: So how to read it "line by line" getchar() ?
Here are three ways to read an entire file into a contiguous buffer:
Figure out the file length, then fread() the whole file. You can figure out the length with fseek() and ftell(), or you can use fstat() on POSIX systems. This will not work on sockets or pipes, it only works on regular files.
Read the file into a buffer which you dynamically expand as you read data using fread(). Typical implementations start with a "reasonable" buffer size and double it each time space is exhausted. This works on any kind of file.
On POSIX, use fstat() to get the file and then mmap() to put the entire file in your address space. This only works on regular files.
You can do the following:
FILE *fp;
int currentBufferSize;
for(i = 0; i < filesToRead; i++)
{
fp = fopen(name, "r");
currentBufferSize = 0;
while(fp != EOF)
fgets(filestring[i], BUFFER_SIZE, fp);
}
Of course you would have to make this in a more robust way, checking if your buffer can hold all the data and so on...
You might use something like the following: where you read each line, carefully check the result and pass it to a datastructure of your choosing. I have not shown how to properly allocate memory, but you can malloc up front and realloc when necessary.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define FILE_BUFFER_SIZE 1024
int file_read_line(FILE *fp, char *buffer)
{
// Read the line to buffer
if (fgets(buffer, FILE_BUFFER_SIZE, fp) == NULL)
return -errno;
// Check for End of File
if (feof(fp))
return 0;
return 1;
}
void file_read(FILE *fp)
{
int read;
char buffer[FILE_BUFFER_SIZE];
while (1) {
// Clear buffer for next line
buffer[0] = '\0';
// Read the next line with the appropriate read function
read = file_read_line(fp, buffer);
// file_read_line() returns only negative numbers when an error ocurred
if (read < 0) {
print_fatal_error("failed to read line: %s (%u)\n",
strerror(errno), errno);
exit(EXIT_FAILURE);
}
// Pass the read line `buffer` to whatever you want
// End of File reached
if (read == 0)
break;
}
return;
}
How do I determine if a file is empty? The file is opened by a C program running on the Windows platform. I want to open a file in append mode, and, if empty, first print a header to it.
// Open CSV & write header
report_csv = fopen("SNR.csv", "a+");
if (!report_csv) {
fprintf(stderr, "Unable to open CSV output file...");
return -1;
}
if (!ftell(report_csv)) {
fprintf(report_csv, "Column A;Column B;Column C\n");
}
// ... print data to file
fclose(report_csv);
I was expecting ftell to return the current file size if the file was not empty, which happens because the code above is looped.
However, ftell always returns 0 and the header is printed multiple times.
I know I could fopen it with r and use fseek/ftell/fclose and then fopen it again with a+, but I think it's possible to do this without opening and closing the file multiple times.
Actually, when fopening a file in append mode, the file pointer is initially at the begining of the file. It moves to the end of it as soon as you write something or use fseek.
I just needed to add fseek(report_csv, 0, SEEK_END); before my if (!ftell(report_csv)).
Let's check this.
Code:
#include <stdio.h>
int main(int argc, char **argv) {
FILE *test;
size_t size;
char buf[100];
/* Truncate file */
test = fopen("test", "w");
if (!test) {
fprintf(stderr, "Cannot open file `test`!\n");
return 1;
}
/* Write something */
fprintf(test, "Something. ");
fclose(test);
/* Open in append */
test = fopen("test", "a+");
if (!test) {
fprintf(stderr, "Cannot open `test` in append mode!\n");
return 1;
}
/* Try to get the file size */
size = ftell(test);
printf("File pointer is: %d\n", size);
fseek(test, 0, SEEK_END);
size = ftell(test);
printf("After `fseek(test, 0, SEEK_END)`, the file pointer is: %d\n", size);
/* Append */
fprintf(test, "And that. ");
fclose(test);
/* Same without fseek */
test = fopen("test", "a+");
if (!test) {
fprintf(stderr, "Cannot open `test` in append mode!\n");
return 1;
}
fprintf(test, "Hello! ");
size = ftell(test);
printf("File size is now: %d\n", size);
fclose(test);
/* Try to read */
test = fopen("test", "r");
if (!test) {
fprintf(stderr, "Unable to open `test` for reading!\n");
return 1;
}
printf("File contents:\n\t");
while (test && !feof(test)) {
fgets(buf, sizeof(buf), test);
printf("%s", buf);
}
/* Cleanup & exit */
fclose(test);
printf("\n\nExiting.\n");
return 0;
}
Output:
File pointer is: 0
After `fseek(test, 0, SEEK_END)`, the file pointer is: 11
File size is now: 28
File contents:
Something. And that. Hello!
Exiting.
When opening a file with fopen with the a+ mode, all writing operations will be performed at the end of the file. You can reposition the internal pointer to anywhere in the file for reading, but writing operations will move it back to the end of file. The initial pointer position for reading is at the beginning of the file.
So you need to call an fseek(pFile, 0, SEEK_END) on your FILE pointer.
You can call _stat() and get the value st_size into struct _stat (you dont need open the file).Declared in sys/types.h followed by sys/stat.h
I don´t know Windows programming, but it can help you: http://msdn.microsoft.com/en-us/library/14h5k7ff.aspx
I want to create an exact copy of a file(.bmp) in c
#include<stdio.h>
int main()
{
FILE *str,*cptr;
if((str=fopen("org.bmp","rb"))==NULL)
{
fprintf(stderr,"Cannot read file\n");
//return 1;
}
if((cptr=fopen("copy.bmp","wb"))==NULL)
{
fprintf(stderr,"Cannot open output file\n");
//return 1;
}
fseek(str, 0, SEEK_END);
long size=ftell(str);
printf("Size of FILE : %.2f MB \n",(float)size/1024/1024);
char b[2];
for(int i=0;i<size;i++)
{
fread(b,1,1,str);
fwrite(b,1,1,cptr);
}
fseek(cptr, 0, SEEK_END);
long csize=ftell(str);
printf("Size of created FILE : %.2f MB \n",(float)csize/1024/1024);
fclose(str);
fclose(cptr);
return 0;
}
Although it creates a file of the same size but windows throws an error while trying to view the newly created copy of bitmap.
Why is this happening?
You have moved the file pointer for the input file to the end of the file before you start reading it. You need to restore it to the beginning.
Change:
fseek(str, 0, SEEK_END);
long size=ftell(str);
to:
fseek(str, 0, SEEK_BEGIN);
long size=ftell(str);
fseek(str, 0, SEEK_SET);
Note that your code is devoid of error checking - if you had at least checked the result of fread then your mistake would have been immediately apparent. Take-home message: don't cut corners when it comes to error-checking - it will pay dividends later.
You need to seek back to the start of the original file because you are continually reading at the EOF and therefore not making a copy of the file contents, just whatever happens to be in your b[] array.
You are not checking the return codes of fread() and fwrite(). If you had been doing that you might have solved this problem from the return codes.
If you check the size of the original file and the copy in bytes, it should tell you the issue.
This code reads a byte and writes a byte.
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define KB 1024
int main()
{
unsigned int ifd,ofd,rcnt;
char buf[KB];
ifd=open("orig.jpg",O_RDONLY);
if(ifd==0)
{
fprintf(stderr,"Cannot read file\n");
//return 1;
}
ofd=open("copy.jpg",O_WRONLY|O_CREAT);
if(ofd==0)
{
fprintf(stderr,"Cannot open output file\n");
//return 1;
}
while(rcnt=read(ifd,buf,KB))
write(ofd,buf,rcnt);
}
~
This is a nice function to copy files! Copy char by char is better than read the whole file because that result (if the file is to long) is a bufferoverflow!
double copy(char *input, char *output) {
FILE *f_in = fopen(input, "r");
FILE *f_out = fopen(output, "a");
if (!f_in || !f_out) {
fclose(f_in);
fclose(f_out);
return -1;
}
int c;
while ((c = fgetc(f_in)) != EOF)
fputc(c, f_out);
fclose(f_in);
fseek(f_out, 0, SEEK_END);
long size = ftell(f_out);
fclose(f_out);
return (double)(size / 1024 / 1024); // MB
}
This function returns the MB of the output file. If it wasn't successfully it return 0.
Use this function like this:
double output;
if ((output = copy("What ever you want to copy", "Where ever it should be printed")) != -1)
printf("Size of file: %lf MB.\n", output);
Hope this will help :)
I copped your first code and also used first solution just you need to add this code to your program :fseek(str, 0, SEEK_SET);and done your copy bitmap will be produce.
I am try to write a buffer so I can remove a lot of null "00" characters in a file. The characters are useless and are completely random. They are wreaking havoc on the searcher in the program. The code below compiles but just seems to hang when a file is passed to it. Any suggestions will be helpful.
void ReadFile(char *name)
{
FILE *dbg;
char *buffer;
unsigned long fileLen;
//Open file
dbg = fopen(dbg, "w+");
if (!dbg)
{
fprintf(stderr, "Unable to open file %s", name);
return;
}
//Get file length
fseek(dbg, 0, SEEK_END);
fileLen = ftell(dbg);
fseek(dbg, 0, SEEK_SET);
//Allocate memory
buffer = (char *)malloc(fileLen+1);
if (!buffer)
{
fprintf(stderr, "Memory error!");
fclose(dbg);
return;
}
//Read file contents into buffer
fread(buffer, fileLen, 1, dbg);
for(i = fileLen-1; i >= 0 && buffer[i] == 0; i--);
i++;
if (i > 0)
{
fwrite(buffer, 1, i, dbg);
}
fclose(dbg);
//Do what ever with buffer
free(buffer);
}
Change
dbg = fopen(dbg, "w+");
to
dbg = fopen(name, "w+");
Also, if you want to read the file, change it then write it, you shouldn't open it with "w+". You should first open the file with "r", read from it, do whatever change you want, then fclose it, then again open it but this time with "w" so that you write over it. After you have opened it in "w"rite mode, you can write the modified buffer back into the file.
You opened a file for writing and then you try to read from it.
Check the return value of fread and all the other calls.