I'm playing with file I/O in C.. I'm trying to use fgets to read data in from one file and output it to another file. The problem is that it always returns NULL and so nothing gets copied to the output file. Here's my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fpIn;
FILE *fpOut;
if ((fpIn = fopen("C:\\testIn.txt", "r") == NULL))
{
printf("Cannot open input file!\n");
exit(1);
}
if ((fpOut = fopen("C:\\testOut.txt", "a") == NULL))
{
printf("Cannot open output file!\n");
exit(1);
}
char buffer[128];
while (fgets(buffer, 128, fpIn) != NULL)
{
fputs(buffer, fpOut);
}
fclose(fpIn);
fclose(fpOut);
system("PAUSE");
return 0;
}
another thing; when I tried using "a+f" in the second arg for fopen, it didn't work.
if ((fpOut = fopen("C:\\testOut.txt", "a") == NULL))
Should be
if ((fpOut = fopen("C:\\testOut.txt", "a")) == NULL)
Same on the input file.
If you are new to C, I'd suggest do one thing at a time to make it easier to track down issues.
e.g.
fpOut = fopen("C:\\testOut.txt", "a");
if(fpOut == NULL) {
...
Related
I'm trying to create a function that checks if a file exists, if it does then it will open it up in order to update it, and if it doesn't exist it will create a new one.
void readFunc(void) {
FILE *input;
char filename[N];
printf("Write textfile: ");
scanf("%s", filename);
if(input == NULL) {
printf("\nFile doesn't exist. Creating a new one!\n\n");
input = fopen(filename, "w+");
} else {
printf("\nFile exists!\n\n");
input = fopen(filename, "r+");
}
}
This is what my code looks like now. I know it might be very wrong but I would like to know how to think in order for it to work.
I will insert pointers later in order for it to work well with the main function.
Because of TOCTOU races, the best way to do this is to drop down a level and use open, which, unlike fopen, lets you specify "open this file for read and write, preserving existing contents, and create it if it doesn't already exist":
FILE *ensure_file(const char *fname)
{
int fd = open(fname, O_RDWR | O_CREAT, 0666);
if (fd == -1) {
perror(fname);
return 0;
}
return fdopen(fd, "r+");
}
The code is almost correct: you should for try with "r+", then "w+ if the file does not exist:
#include <errno.h>
#include <stdio.h>
void readFunc(void) {
FILE *input;
char filename[256];
printf("Write textfile: ");
if (scanf("%255s", filename) != 1)
exit(1);
input = fopen(filename, "r+");
if (input != NULL) {
printf("\nFile exists\n");
} else {
printf("\nFile doesn't exist. Creating a new one!\n\n");
input = fopen(filename, "w+");
if (input == NULL) {
printf("Cannot create file: %s\n", strerror(errno));
return;
}
}
[...]
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person
{
char name[10];
char size[6];
char timestamp[15];
};
int main ()
{
FILE *outfile;
// open file for writing
outfile = fopen ("ads.txt", "a");
if (outfile == NULL)
{
fprintf(stderr, "\nError opend file\n");
exit (1);
}
struct person input1 = {"runner", "100", "4376482682"};
//struct person input2 = {"maze", "300", "3232365436"};
// write struct to file
fwrite (&input1, sizeof(struct person), 1, outfile);
//fwrite (&input2, sizeof(struct person), 1, outfile);
if(fwrite != 0)
printf("contents to file written successfully !\n");
else
printf("error writing file !\n");
// close file
fclose (outfile);
FILE *infile;
struct person input;
infile = fopen ("ads.txt", "r");
if (infile == NULL)
{
fprintf(stderr, "\nError opening file\n");
exit (1);
}
// read file contents till end of file
char name[10] = "maze";
char size[6] = "500";
char timestamp[15] = "437838322";
int remaining_size = 100;
int alreadythere =0;
//unpcoming file size
int incoming_file_size = 200;
int target_file_size_toremove = incoming_file_size - remaining_size;
while(fread(&input, sizeof(struct person), 1, infile)){
if(target_file_size_toremove > 0) {
int x = atoi(input.size);
if(target_file_size_toremove < x) {
strcpy(input.name, name);
strcpy(input.size, size);
strcpy(input.timestamp, timestamp);
}
}else {
if(strcmp(input.name, name) == 0) { // if name is eqUAL
if(strcmp(input.size, size) != 0) {
strcpy(input.size, size);
}
if(strcmp(input.timestamp, timestamp) !=0) {
strcpy(input.timestamp, timestamp);
}
alreadythere = 1;
}
printf ("id = %s name = %s %s\n", input.name,
input.size, input.timestamp);
}
}
if(alreadythere == 0) {
struct person incoming = {name, size, timestamp};
fwrite (&incoming, sizeof(struct person), 1, outfile);
}
// close file
fclose (infile);
return 0;
}
The code is in C language. I want to update the size variable when name is equal to "maze". How I can do it, while reading from file?
first the data that is writing in file is -
runner 100 4376482682
maze 300 3232365436
After updating -
runner 100 4376482682
maze 100 3232365436
size should updated from 300 to 100.
I have fixed a number of small bugs in your code related to opening the file in correct mode and checking if fwrite and fread where successful. Then I added the part you where really asking: update the record "maze".
To update the record, we need to read it, change the value and write it back to the file exactly where we have read it. So before reading a record, we query the current file pointer with ftell and before writing, we call fseek to move the file pointer back to the place we read. A call to fflush (another fseek would do as well) is required so that the next fread take place at the correct position.
For testing, I added a third record after "maze" so that we can see - by looking at the file content - that we don't overwrite data.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person
{
char name[10];
char size[6];
char timestamp[15];
};
int main()
{
FILE* outfile;
// open file for writing binary
outfile = fopen("ads.txt", "wb");
if (outfile == NULL) {
fprintf(stderr, "\nError opening file\n");
exit(1);
}
struct person input1 = { "runner", "100", "4376482682" };
struct person input2 = { "maze", "300", "3232365436" };
struct person input3 = { "street", "400", "4232365486" };
// write struct to file, checking for success
if ((fwrite(&input1, sizeof(struct person), 1, outfile) != 1) ||
(fwrite(&input2, sizeof(struct person), 1, outfile) != 1) ||
(fwrite(&input3, sizeof(struct person), 1, outfile) != 1))
printf("error writing file !\n");
else
printf("contents to file written successfully !\n");
// close file
fclose(outfile);
FILE* infile;
struct person input;
// Open for both reading and writing, binary
infile = fopen("ads.txt", "r+b");
if (infile == NULL) {
fprintf(stderr, "\nError opening file for update\n");
exit(1);
}
// read file contents till end of file, update "maze"
while (1) {
long pos = ftell(infile);
if (pos < 0) {
fprintf(stderr, "\nError getting file position\n");
break;
}
if (fread(&input, sizeof(struct person), 1, infile) != 1)
break;
// update the value of size here, if name is equal to "maze"
printf("id = %s name = %s %s\n", input.name, input.size, input.timestamp);
if (strcmp(input.name, "maze") == 0) {
if (fseek(infile, pos, SEEK_SET) != 0) {
fprintf(stderr, "\nError moving file pointer\n");
break;
}
strcpy(input.size, "100");
if (fwrite(&input, sizeof(struct person), 1, infile) != 1) {
fprintf(stderr, "\nError writing file\n");
break;
}
// fflush() is required so that fread() take place a the correct position
if (fflush(infile) != 0) {
fprintf(stderr, "\nError flushing file\n");
break;
}
printf(" Updated id = %s name = %s %s\n", input.name, input.size, input.timestamp);
// Since this code update a single record, we could break the loop
}
}
// close file
fclose(infile);
return 0;
}
I can't figure out why this isn't working.
#include <stdio.h>
int main(void) {
FILE *in, *out;
// char *FULLPATH = "C:\\Users\\Jay\\c\\workspace\\I-OFiles\\in.txt\\ ";
// char *mode = "r";
// in = fopen(FULLPATH, mode);
//
// if (in == NULL) {
// perror("Can't open in file for some reason\n");
// exit (1);
// }
out = fopen("C:\\Users\\Jay\\c\\workspace\\I-OFiles\\out.txt", "w");
if (out == NULL) {
perror("Can't open output file for some reason \n");
exit(1);
}
fprintf(out, "foo U");
fclose(in);
fclose(out);
return 0;
}
if I remove the // from the commented lines, the error compiler gives is
: Invalid argument
I don't understand why (I read all the other threads related, and nothing).
It does actually write the out.txt file OK, so it doesn't seem like a path misspelled problem.
Remove backslash after in.txt.
The input file name seems bogus:
"C:\\Users\\Jay\\c\\workspace\\I-OFiles\\in.txt\\ "
The filename is just a single space " " and in.txt is probably not a directory.
Change the code to:
const char *FULLPATH = "C:\\Users\\Jay\\c\\workspace\\I-OFiles\\in.txt";
Or preferably:
const char *FULLPATH = "C:/Users/Jay/c/workspace/I-OFiles/in.txt";
for better portability as forward slashes work in Windows as well as in Unix.
Furthermore, it is easy to provide more information as to why fopen() failed to open the files.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
FILE *in, *out;
in = fopen("C:/Users/Jay/c/workspace/I-OFiles/in.txt", "r");
if (in == NULL) {
perror("Cannot open input file");
exit(1);
}
out = fopen("C:/Users/Jay/c/workspace/I-OFiles/out.txt", "w");
if (out == NULL) {
fclose(in);
perror("Cannot open output file");
exit(1);
}
fprintf(out, "foo U");
fclose(in);
fclose(out);
return 0;
}
Change backslash to slash.
Maybe you don't have permissions or something like that.
out = fopen("C://Users//Jay//c//workspace//I-OFiles//out.txt", "w");
if (!out)
perror("fopen");
return 0;
Here is a simple program that should copy the content of one
file named copyme into a file here. I have created copyme with a little text in it by the following commands:
touch copyme.txt
open copyme.txt
Then I typed in text, and saved the file with
touch copyme.txt command.
Then I compiled a program:
// Program to copy one file ot another
#include <stdio.h>
int main (void)
{
char in_name[64], out_name[64];
FILE *in, *out;
int c;
// get file names from user
printf("Enter name of file to be copied: ");
scanf("%63s", in_name);
printf("Entere name of output file: ");
scanf("%63s", out_name);
// open input and output files
if ( (in = fopen(in_name, "r")) == NULL)
{
printf("Can't open %s for reading.\n", in_name);
return 1;
}
if ( (out = fopen(out_name, "w")) == NULL)
{
printf("Can't open %s for writing.\n", out_name);
return 2;
}
while ((c = getc(in)) != EOF)
putc(c, out);
// Close open files
fclose (in);
fclose (out);
printf("File has been copied\n");
return 0;
}
And ran it in terminal.
Here is the output:
Enter name of file to be copied: copyme
Entere name of output file: here
Can't open copyme for reading.
The compiler doesn't recognize copyme file, although it is
physically exists in the folder (I see it, I open it, I read
it).
I would be grateful for help. I am new to this things.
Thank you!
change
if ( (in = fopen(in_name, "r")) == NULL)
{
printf("Can't open %s for reading.\n", in_name);
return 1;
}
to
#include <errno.h>
if ( (in = fopen(in_name, "r")) == NULL)
{
perror("Can't open file for reading.\n");
return 1;
}
you will get a human readable message telling you why it cant read the file
#include <stdio.h>
#include <stdlib.h>
int main() {
int c;
FILE *poem = fopen("short.txt", "r");
FILE *html = fopen("index.html", "w");
if (poem == NULL){
perror("Error in opening file");
return(-1);
}
if (html == NULL){
perror("Error in opening file");
return(-1);
}
while((c = fgetc(poem)) != EOF) {
c = getc(poem);
fputc(c, html);
}
fclose (poem);
fclose (html);
return 0;
}
I've been searching and trying but I can't figure it out. My read file has less than a sentence of words, and then when it outputs it to index.html it's all jumbled up. I don't really understand know whats wrong with the code. Any help will be appreciated. Thanks!
You are doing 2 reads for each write
while((c = fgetc(poem)) != EOF) { // read
c = getc(poem); // read
fputc(c, html); // write
}