unable to read text from file in C - c

I have this code that's supposed to read from a text file and print its content but I keep getting "Unable to open file."
#include <stdio.h>
#include <string.h>
#define MAX 4000
int main(void)
{
FILE *bkptr;
char buffer[MAX];
bkptr = fopen("defoe-robinson-103.txt", "r");
// If file dow not open
if (bkptr == NULL) {
puts("Unable to open file.");
}
// If file open
else {
// Read each line form file until EOF
while (fgets(buffer, MAX, bkptr)) {
// Print the line
puts(buffer);
}
// Close the file
fclose(bkptr);
}
}

Related

Reading a pdf file with fread in C does not end up as expected

I am trying to read from a pdf file and write into another file where I run to the problem.
In the while loop, fread reads only 589 bytes which is expected to be 1024 for the first time.
In the second loop, fread reads 0 bytes.
I am sure that the pdf file is beyond 1024 bytes.
Here is a similar problem. The phenomenon is the same. But I do not use strlen() which causes that problem.
So how can I resolve the problem?
My code is here:
#include <stdio.h>
#define MAXLINE 1024
int main() {
FILE *fp;
int read_len;
char buf2[MAXLINE];
FILE *fp2;
fp2 = fopen("test.pdf", "w");
if ((fp = fopen("LearningSpark.pdf", "r")) == NULL) {
printf("Open file failed\n");
}
while ((read_len = fread(buf2, sizeof(char), MAXLINE, fp)) > 0) {
int write_length = fwrite(buf2, sizeof(char), read_len, fp2);
if (write_length < read_len) {
printf("File write failed\n");
break;
}
}
return 0;
}
fopen(filename, "r") is system dependent. See this post on what may happen to the data you read if you are on Windows, for example. Basically it is related to how certain characters are translated on different systems in text mode, ie., \n is "End-of-Line" on Unix-type systems, but on Windows it is \r\n.
Important: On Windows, ASCII char 27 will result in End-Of-File, if reading in text mode, "r", causing the fread() to terminate prematurely.
To read a binary file, use the "rb" specifier. Similarly for "w", as mentioned here, you should use "wb" to write binary data.
Binary files such as pdf files must be open in binary mode to prevent end of line translation and other text mode handling on legacy systems such as Windows.
Also note that you should abort when fopen() fails and you should close the files.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define MAXLINE 1024
int main() {
char buf2[MAXLINE];
int read_len;
FILE *fp;
FILE *fp2;
if ((fp = fopen("LearningSpark.pdf", "rb")) == NULL) {
fprintf(stderr, "Open file failed for %s: %s\n", "LearningSpark.pdf", strerror(errno));
return 1;
}
if ((fp2 = fopen("test.pdf", "wb")) == NULL) {
fprintf(stderr, "Open file failed for %s: %s\n", "test.pdf", strerror(errno));
fclose(fp);
return 1;
}
while ((read_len = fread(buf2, 1, MAXLINE, fp)) > 0) {
int write_length = fwrite(buf2, 1, read_len, fp2);
if (write_length < read_len) {
fprintf(stderr, "File write failed: %s\n", strerror(errno));
break;
}
}
fclose(fp);
fclose(fp2);
return 0;
}

Storing .raw File Data as a Pointer Using C

I am attempting to read a '.raw' file which stores the contents of an image that was taken on a camera using C. I would like to store these contents into a uint16_t *.
In the following code I attempt to store this data into a pointer, using fread(), and then write this data into a test file, using fwrite(), to check if my data was correct.
However, when I write the file back it is completely black when I check it.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#define MAX_ROW 2560
#define MAX_COL 2160
int main()
{
char filename[32] = "image1.raw";
FILE * image_raw = fopen(filename, "rb");
fseek(image_raw, 0, 2);
long filesize = ftell(image_raw);
/*READ IMAGE DATA*/
uint16_t * image_data_ptr;
image_data_ptr = (uint16_t *)malloc(sizeof(uint16_t)*MAX_ROW*MAX_COL);
fread(image_data_ptr, sizeof(uint16_t), filesize, image_raw);
fclose(image_raw);
/*TEST WRITING THE SAME DATA BACK INTO TEST RAW FILE*/
FILE *fp;
fp = fopen("TEST.raw", "w");
fwrite(image_data_ptr, sizeof(uint16_t), filesize, fp);
fclose(fp);
return 0;
}
There are multiple issues with your code:
lack of error handling.
not seeking the input file back to offset 0 after seeking it to get its size. Consider using stat() or equivalent to get the file size without having to seek the file at all.
not dividing filesize by sizeof(uint16_t) when reading from the input file, or writing to the output file. filesize is expressed in bytes, but fread/fwrite are expressed in number of items of a given size instead, and your items are not 1 byte in size.
not opening the output file in binary mode.
leaking the buffer you allocate.
With that said, try something more like this instead:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main()
{
char filename[32] = "image1.raw";
FILE *image_raw = fopen(filename, "rb");
if (!image_raw) {
fprintf(stderr, "Can't open input file\n");
return -1;
}
if (fseek(image_raw, 0, SEEK_END) != 0) {
fprintf(stderr, "Can't seek input file\n");
fclose(image_raw);
return -1;
}
long filesize = ftell(image_raw);
if (filesize == -1L) {
fprintf(stderr, "Can't get input file size\n");
fclose(image_raw);
return -1;
}
rewind(image_raw);
long numSamples = filesize / sizeof(uint16_t);
/*READ IMAGE DATA*/
uint16_t *image_data_ptr = (uint16_t*) malloc(filesize);
if (!image_data_ptr) {
fprintf(stderr, "Can't allocate memory\n");
fclose(image_raw);
return -1;
}
size_t numRead = fread(image_data_ptr, sizeof(uint16_t), numSamples, image_raw);
if (numRead != numSamples) {
fprintf(stderr, "Can't read samples from file\n");
free(image_data_ptr);
fclose(image_raw);
return -1;
}
fclose(image_raw);
/*TEST WRITING THE SAME DATA BACK INTO TEST RAW FILE*/
FILE *fp = fopen("TEST.raw", "wb");
if (!fp) {
fprintf(stderr, "Can't open output file\n");
free(image_data_ptr);
return -1;
}
if (fwrite(image_data_ptr, sizeof(uint16_t), numSamples, fp) != numSamples) {
fprintf(stderr, "Can't write to output file\n");
fclose(fp);
free(image_data_ptr);
return -1;
}
fclose(fp);
free(image_data_ptr);
return 0;
}
You have already a great answer and useful comments
anyway, consider that if you want to iterate over your file, loaded in memory as a whole, as an array of unsigned words:
if the file size could be odd what to do at the last byte/word
you may read the file as a whole in a single call, after having the file size determined
fstat() is the normal way to get the file size
get the file name from the command line as an argument is much more flexible than recompile the program or change the file name in order to use the program
The code below does just that:
uses image.raw as a default for the file name, but allowing you to enter the file name on the command line
uses fstat() to get the file size
uses a single fread() call to read the entire file as a single record
A test using the original program file as input:
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 20/07/2021 17:40 1067 main.c
PS > gcc -Wall -o tst main.c
PS > ./tst main.c
File is "main.c". Size is 1067 bytes
File "main.c" loaded in memory.
PS > ./tst xys
File is "xys". Could not open: No such file or directory
The C example
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
int main(int argc, char**argv)
{
const char* default_file = "image.raw";
char f_name[256];
if (argc < 2)
strcpy(f_name, default_file);
else
strcpy(f_name, argv[1]);
FILE* F = fopen(f_name, "rb");
if (F == NULL)
{
printf("File is \"%s\". ", f_name);
perror("Could not open");
return -1;
}
struct stat info;
fstat(_fileno(F),&info);
printf("File is \"%s\". Size is %lu bytes\n", f_name, info.st_size);
uint16_t* image = malloc(info.st_size);
if (image == NULL)
{ perror("malloc() error");
return -2;
};
if (fread(image, info.st_size, 1, F) != 1)
{ perror("read error");
free(image);
return -3;
};
// use 'image'
printf("File \"%s\" loaded in memory.\n", f_name);
free(image);
fclose(F);
return 0;
}

my copy file function isn't working as expected

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

How to implement a FIFO log file?

I am trying to use a FIFO file to store buffered log entries for my application if the network connection is lost. I thought when reading from a FIFO file it would be deleted completely thus it would be "popped" from the log queue.
However, my approach kept logging reading the same text indefinitely. Perhaps it would be easier to read all entries into a buffer and try to log them to the database and write back all entries that couldn't be logged.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
/**
* First argument is the filename
* Second argument is the log message
* Third argument is the severity
*/
int main(int argc, char **argv) {
int err, severity;
char c;
char *fifoName = "/tmp/bufferedlog";
char src[100], msg[100];
FILE *fp;
/**
* if the program has exactly three arguments it will push
* a new log entry to the queue.
*/
if(argc == 3) {
fp = fopen(fifoName, "w");
if(fp == NULL) {
err = mknod(fifoName, S_IFIFO | 0600, 0);
if(err < 0){
fprintf(stderr, "Unable to create fifo: %s\n",fifoName);
exit(EXIT_FAILURE);
}
fp = fopen(fifoName, "w");
if(fp == NULL) {
fprintf(stderr, "Unable to open fifo for writing\n");
exit(EXIT_FAILURE);
}
}
fprintf(fp, "\"%s\" \"%s\" %d ","My Application", argv[1], atoi(argv[2]));
fflush(fp);
fclose(fp);
return 0;
}
fp = fopen(fifoName, "r");
if(fp == NULL) {
fprintf(stderr, "Unable to open fifo for reading\n");
exit(EXIT_FAILURE);
}
/**
* it will now try to read the log entry from the fifo file.
*/
while(1) {
if(fscanf(fp,"\"%[^\"]\" \"%[^\"]\" %d", src, msg, &severity) < 0) { // ignore the overflow bugs
goto finish;
}
fprintf(stdout, "Do you really want to log \"%s (%d):%s\" to database [y/n]?\n", src, severity, msg);
scanf(" %c",&c);
if(c=='y') {
/* logs to database here */
/* if it fails to log to database it will break out of this loop */
fprintf(stdout, "Pushed log entry to database.\n");
}else {
goto finish;
}
}
fclose(fp);
fp = fopen(fifoName, "w");
/**
* if the database connection failed it fill put the log entry back into
* the queue and try again when the program starts next time.
*/
if(fp == NULL) {
fprintf(stderr, "Unable to open fifo for writing\n");
exit(EXIT_FAILURE);
}
fprintf(fp, "\"%s\" \"%s\" %d ", src, msg, severity);
fflush(fp);
finish:
fclose(fp);
return 0;
}
Please ignore the overflow bugs with scanf. My attempt doesn't work, here is the psuedocode of my program.
if argc is equal to three then
write log entry to fifo file
end
while there is data in fifo file do
read log entry from fifo file and delete it from fifo file
try logging entry to database
if failed then
break out of while loop
end
end
write log entry back to fifo file

Copying contents of text file using file handling

I created a text file named "test.txt" and then executed this program to copy the contents of "test.txt" to "file.txt". But it is showing an error while opening the file itself, i.e., fr==NULL is true.
What is wrong with the program?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int i,count=0;
char ch;
FILE *fw,*fr;
fw = fopen("file.txt", "a+");
fr = fopen("test.txt", "r+");
fseek(fr,0,SEEK_SET);
if(fr==NULL)
{
printf("Error while opening the file.\n");
exit(0);
}
while((ch=getc(fr))!=EOF)
{
putc(ch,fw);
}
fclose(fw);
fclose(fr);
return 0;
}
If fopen returns NULL, check the value of errno, e.g. by including <errno.h> and using the perror("Error while opening the file"); instead of the printf statement.

Resources