C - Reading a File from Command Line? - c

Suppose I had a file that I wanted to read.
./a.out file // where file is a argument
The Program being:
//program.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char ch, file_name[25] = argv[1]; //??? Is the issue here?
FILE *fp;
fp = fopen(file_name,"r");
if( fp == NULL )
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
printf("The contents of %s file are :\n", file_name);
while( ( ch = fgetc(fp) ) != EOF )
printf("%c",ch);
fclose(fp);
return 0;
}
EDITED:
When compiling with gcc
gcc program.c
program.c: file not recognized: File format not recognized
Is the error Im getting.

//program.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SIZEBUF 1024
int main(int argc, char *argv[])
{
int fd;
char buffer[SIZEBUF];
if (argc < 2)
{
printf("Missing file\n");
return (EXIT_FAILURE);
}
fd = open(argv[1], O_RDONLY);
if (fd == -1)
{
printf("Some error occured\n");
return (EXIT_FAILURE);
}
printf("The contents of %s file are :\n", argv[1]);
while(read(fd, buffer, SIZEBUF) > 0 )
printf("%s", buffer);
close(fd);
return (EXIT_SUCCESS);
}
Try this.

Yes.
But if you're in doubt, you could try printing the things in argv.

Related

Print out a given argument files content in C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv){
char** alllines;
int size=0;
if(argc < 2){
}else{
for(int i = 0; i < argc; i++){
FILE* fp;
unsigned int bufferSize = 1024;
char* line = malloc(sizeof(char)*bufferSize);
char* filename = argv[i];
fp = fopen(filename, "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while (getline(&line, &bufferSize, fp) != -1){
printf("%s", line);
}
fclose(fp);
if (line)
free(line);
exit(EXIT_SUCCESS);
}
}
return(0);
}
Here's how I compile and run the code:
gcc program.c
Here's how I run it:
./a.exe test.txt
Here's the test file(it's in the same directory as the c file):
12345
asddfhdfh
abcdefgh
765431
Here's what it returns:
MZÉ$
Here's what it should return:
12345
asddfhdfh
abcdefgh
765431

Confused with the st_ino?

#include "stdio.h"
#include <sys/stat.h>
int
main(int argc, char *argv[]) {
struct stat buf;
//int fd = open("./fstatat.c", "r");
//int fd2 = fstatat(fd, "a.txt", &buf, 0);
//printf("%d\n", buf.st_ino);
stat("./fstatat.c", &buf);
printf("%d\n", buf.st_ino);
return 0;
}
if i use the function stat to get a struct stat, the st_ino is the same as the i-node number with the ls -i.
1305609
[inmove#localhost chapter-four]$ ls -i
1305607 a.txt 1305606 fstatat.bin 1305609 fstatat.c 1305605 tmp.txt
buf if i use the function fstat, the st_ino is always the 4195126.
anyone can tell me why this happen?
The problem is that you are not using open correctly and don't check the return values for errors. So you are then calling fstat on the invalid file descriptor value -1 returned by open on error, which will also fail and not touch buf at all, so the uninitialized garbage in the struct is still there (4195126, hex 0x400336 smells a lot like a return address of a previous function call still being on the stack or something like this.)
As davmac already pointed out, the second parameter to open must be a list of flags, which are numeric. Check the docs.
So, the correct code would be:
#include "stdio.h"
#include <sys/stat.h>
#include <sys/fcntl.h> // for the O_RDONLY constant
#include <errno.h> // for error output
int main(int argc, char *argv[]) {
struct stat buf;
int fd = open("./fstatat.c", O_RDONLY);
if(fd == -1) {
printf("Error calling open: %s\n", strerror(errno));
} else {
if(fstat(fd, &buf) == -1) {
printf("Error calling fstat: %s\n", strerror(errno));
} else {
printf("%d\n", buf.st_ino);
if(close(fd) == -1) {
printf("Error calling close: %s\n", strerror(errno));
}
}
}
return 0;
}

Contents of file not being printed in terminal

Hi I am trying to read from a file and print it on terminal. But fwrite() does not print anything. Can anyone please help! I cannot see the output from the file on the terminal. After debugging all I can see is program is not entering into while loop used before fwrite().
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#define BUF_SIZE 128
int main(int argc, char* argv[])
{
int BATT_fd, ret_write, ret_read, i;
char buffer[BUF_SIZE];
if(argc != 2)
{
printf ("\nUsage: cp file1 file2\n");
return 1;
}
BATT_fd = open (argv [1], O_RDWR | O_CREAT, S_IRWXU);
if (BATT_fd == -1)
{
perror ("open");
return 2;
}
printf("\n file opened successfully with file desc %d\n", BATT_fd);
printf("enter data into file\n");
scanf("%[^\n]", buffer);
if((ret_write = write (BATT_fd, &buffer, BUF_SIZE)) == 0)
{
printf("nothing is write");
}
else if((ret_write = write (BATT_fd, &buffer, BUF_SIZE)) == -1)
{
printf("write error");
}
else
{
printf("wrote %d characters to file\n", ret_write);
printf("address writeen is %x\n", buffer[i]);
}
if((ret_read = read(BATT_fd, &buffer, BUF_SIZE)) > 0)
{
perror("read");
return 4;
}
else
{
while((ret_read = read (BATT_fd, &buffer, BUF_SIZE)) > 0)
{
fwrite(buffer, 1, ret_read, stdout);
}
}
close (BATT_fd);
return 0;
}
output:
Before reading data from file, you need to move current position in file to the begining. That's because your write operations have moved current position to the end of file, so there is nothing left for reading ;).
see fseek
EDIT:
lseek would be better in your case (see comments)

How to distinguish a file pointer points to a file or a directory?

When I do:
FILE * fp = fopen("filename", "r");`
How can I know the file pointer fp points to a file or a directory? Because I think both cases the fp won't be null. What can I do?
The environment is UNIX.
i've found this near by:
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
int main (int argc, char *argv[]) {
int status;
struct stat st_buf;
status = stat ("your path", &st_buf);
if (status != 0) {
printf ("Error, errno = %d\n", errno);
return 1;
}
// Tell us what it is then exit.
if (S_ISREG (st_buf.st_mode)) {
printf ("%s is a regular file.\n", argv[1]);
}
if (S_ISDIR (st_buf.st_mode)) {
printf ("%s is a directory.\n", argv[1]);
}
}
You could use fileno() to get the file discriptor for the already opened file, and then use fstat() on the file descriptor to have a struct stat returned.
It's member st_mode carries info on the file.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main()
{
FILE * pf = fopen("filename", "r");
if (NULL == pf)
{
perror("fopen() failed");
exit(1);
}
{
int fd = fileno(pf);
struct stat ss = {0};
if (-1 == fstat(fd, &ss))
{
perror("fstat() failed");
exit(1);
}
if (S_ISREG (ss.st_mode))
{
printf ("Is's a file.\n");
}
else if (S_ISDIR (ss.st_mode))
{
printf ("It's a directory.\n");
}
}
return 0;
}
On Windows, Call GetFileAttributes, and check for the FILE_ATTRIBUTE_DIRECTORY attribute.
Check this and this.

How to send a file through a named pipe in C?

I have two programs, server and client. Server should read a file and then send its content through a named pipe to client. But my server reads only two chars from file, and then exits. What is wrong with this code?
server.c:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define FIFO_NAME "american_maid"
int main(void)
{
char line[300];
int num, fd;
FILE *fp;
fp = fopen("out.txt","r");
mknod(FIFO_NAME, S_IFIFO | 0666, 0);
printf("waiting for readers...\n");
fd = open(FIFO_NAME, O_WRONLY);
printf("got a reader--type some stuff\n");
while (fgets(line, sizeof(line), fp)) {
if ((num = write(fd, line, strlen(line))) == -1)
perror("write");
else
printf("speak: wrote %d bytes\n", num);
}
fclose(fp);
return 0;
}
client.c:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define FIFO_NAME "american_maid"
int main(void)
{
char s[300];
int num, fd;
mknod(FIFO_NAME, S_IFIFO | 0666, 0);
printf("waiting for writers...\n");
fd = open(FIFO_NAME, O_RDONLY);
printf("got a writer\n");
do {
if ((num = read(fd, s, 300)) == -1)
perror("read");
else {
s[num] = '\0';
printf("tick: read %d bytes: \"%s\"\n", num, s);
}
} while (num > 0);
return 0;
}
When I run the code shown below using the command sequence:
$ ln -s server.c out.txt
$ ./client &
$ ./server
$
I get a copy of the source code printed by the client program. Similarly when I run the commands using:
$ ./server &
$ ./client
$
The revised code is not modified all that significantly. It avoids do { } while(...) loops — they're so seldom really beneficial — and is very careful about not overflowing buffers. The code also has superfluous headers removed.
server.c
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define FIFO_NAME "american_maid"
int main(void)
{
const char infile[] = "out.txt";
FILE *fp = fopen(infile, "r");
if (fp == 0)
{
fprintf(stderr, "Failed to open %s for reading", infile);
return(1);
}
mknod(FIFO_NAME, S_IFIFO | 0666, 0);
printf("waiting for readers...\n");
int fd = open(FIFO_NAME, O_WRONLY);
if (fd > 0)
{
char line[300];
printf("got a reader--type some stuff\n");
while (fgets(line, sizeof(line), fp))
{
int len = strlen(line);
int num = write(fd, line, len);
if (num != len)
perror("write");
else
printf("speak: wrote %d bytes\n", num);
}
close(fd);
}
fclose(fp);
return 0;
}
client.c
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#define FIFO_NAME "american_maid"
int main(void)
{
const char outfile[] = "client.out";
FILE *fp = fopen(outfile, "w");
if (fp == 0)
{
fprintf(stderr, "Failed to open %s for writing\n", outfile);
return 1;
}
printf("waiting for writers...\n");
mknod(FIFO_NAME, S_IFIFO | 0666, 0);
int fd = open(FIFO_NAME, O_RDONLY);
if (fd > 0)
{
int num;
char s[300];
printf("got a writer\n");
while ((num = read(fd, s, sizeof(s))) > 0)
{
printf("tick: read %d bytes: \"%.*s\"\n", num, num, s);
fprintf(fp, "%.*s", num, s);
}
close(fd);
}
fclose(fp);
return 0;
}
Note that this version writes its output to file client.out; even when given a file with some very long lines to process (2049 bytes including the newline at the end), the output in client.out exactly matches the input in out.txt.
Remove the line mknod(FIFO_NAME, S_IFIFO | 0666, 0); from the file client.c. Then the program will work as expected. Server will create a file and sent the content of the file to fifo.

Resources