I have fixed some syntactical errors in my code and now the program compiles fine. But when I execute the program the outputFile is empty. outputFile should have contents of inputFile in reverse order. I am trying to debug code in CodeLite IDE.
I need to debug the code with two arguments passed (inputFile and outputFile). I don't seem to find that option in CodeLite IDE. How do I do that ?
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUFFER_SIZE 256
int main (int argc, char *argv[]){
FILE *inputFile, *outputFile;
int fileSize;
int pointer;
char buffer[BUFFER_SIZE];
/* Check for correct user's inputs. */
if( argc !=3 ) {
fprintf(stderr, "USAGE: %s inputFile outputFile.\n", argv[0]);
exit(-1);
}
/* Make sure input file exists. */
if( (inputFile = fopen(argv[1], O_RDONLY))) {
fprintf(stderr, "Input file doesn't exist.\n");
exit(-1);
}
/* Create output file, if it doesn't exist. Empty the file, if it exists. */
if((outputFile = fopen(argv[2], "a+"))) {
fclose(inputFile);
exit(-1);
}
/* Find the size of the input file. */
fileSize = fseek(inputFile, 0, SEEK_END);
/* Read input file and write to output file in reversed order.*/
for(pointer=fileSize-1; pointer>=0; pointer--) {
/*Write content in the buffer to the output file */
while(!feof(inputFile))
{
fgets(buffer, BUFFER_SIZE, inputFile); //reads 256 bytes at a time
fputs (buffer , outputFile );
}
}
fclose(inputFile);
fclose(outputFile);
return(0);
}
http://codelite.org/LiteEditor/ProjectSettings:
Project Settings >> General >> Command arguments
Right click on the project folder
Select project settings
General -> Execution -> Program Arguments
Related
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;
}
I understand that popen doesn't allow simultaneous read and write.
To get around this, I created two files, 1.c for writing, and 2.c for reading. The files are included below.
When I run 1.out, I get the expected output on stdout:
bodhi#bodhipc:~/Downloads$ ./1.out
Stockfish 11 64 BMI2 by T. Romstad, M. Costalba, J. Kiiski, G. Linscott
bodhi#bodhipc:~/Downloads$
However, 2.out doesn't give any output on stdout:
bodhi#bodhipc:~/Downloads$ ./2.out
bodhi#bodhipc:~/Downloads$
Where am I going wrong?
1.c:
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] )
{
FILE *fp;
char path[1035];
/* Open the command for writing. */
fp = popen("./stockfish", "w");
if (fp == NULL) {
printf("Failed to run command\n" );
exit(1);
}
fprintf(fp,"uci\n");
/* close */
pclose(fp);
return 0;
}
2.c:
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] )
{
FILE *fp;
char path[1035];
/* Open the command for reading. */
fp = popen("./1.out", "r");
if (fp == NULL) {
printf("Failed to run command\n" );
exit(1);
}
/* Read the output a line at a time - output it.*/
while (fgets(path, sizeof(path), stdout) != NULL) {
printf("%s", path);
printf("Done!\n");
}
/* close */
pclose(fp);
return 0;
}
while (fgets(path, sizeof(path), stdout) != NULL) {
you don't want to read from stdout, instead:
while (fgets(path, sizeof(path), fp) != NULL) {
I am writing a C program in Ubuntu operating system. I provide an input text file containing string of characters.The program is required to read and manipulate ONE CHARACTER at time and print the whole content of input file in reverse.
When I compile program, I get following error:
reverseFileContent.c: In function ‘main’:
reverseFileContent.c:51:16: warning: passing argument 1 of ‘feof’ makes pointer from integer without a cast [-Wint-conversion]
while(!feof(inputFile))
Can you please explain the error message to me.
Below is the program:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUFFER_SIZE 256
int main (int argc, char *argv[]){
FILE *inputFile, *outputFile;
int fileSize;
int pointer;
char buffer[BUFFER_SIZE];
/* Check for correct user's inputs. */
if( argc !=3 ) {
fprintf(stderr, "USAGE: %s inputFile outputFile.\n", argv[0]);
exit(-1);
}
/* Make sure input file exists. */
if( (inputFile = fopen(argv[1], O_RDONLY))) {
fprintf(stderr, "Input file doesn't exist.\n");
exit(-1);
}
/* Create output file, if it doesn't exist. Empty the file, if it exists. */
if((outputFile = fopen(argv[2], "a+"))) {
fclose(inputFile);
exit(-1);
}
/* Find the size of the input file. */
fileSize = fseek(inputFile, 0, SEEK_END);
/* Read input file and write to output file in reversed order.
* Use lseek() to move the file pointer to the ith position.
* To set the file pointer to a position use the SEEK_SET flag in lseek().
*/
for(pointer=fileSize-1; pointer>=0; pointer--) {
/* INSERT YOUR CODE HERE */
/*
* In a loop:
* - Read input file into a buffer
* Don't read one byte at a time! Try to read BUFFER_SIZE (i.e., 256) bytes at a time.
* - Write content in the buffer to the output file
*/
while(!feof(inputFile))
{
fgets(buffer, BUFFER_SIZE, inputFile); //reads 256 bytes at a time
fputs (buffer , outputFile );
}
}
fclose(inputFile);
fclose(outputFile);
return(0);
}
I want to write in file chunkcombined.playlist located at the path /var/streaming/playlists/chunkcombined/chunkcombined.playlist using C.
As the files (small chunks of video) get received through a socket, I want to add them automatically to a playlist.
For that I want to write the following lines in the file chunkcombined.playlist using C:
"/usr/local/movies//chunk0.mp4" 1
"/usr/local/movies//chunk1.mp4" 1
"/usr/local/movies//chunk2.mp4" 1
"/usr/local/movies//chunk3.mp4" 5
"/usr/local/movies//chunk4.mp4" 5
How can I write into a file at particular path in Linux using C?
Use fopen() and fputs() functions.
Full example (with excessive comments):
#include <stdio.h>
int main(void)
{
/* where to write */
const char filepath[] =
"/var/streaming/playlists/chunkcombined/chunkcombined.playlist";
/* what to write */
const char output_lines[] =
"\"/usr/local/movies//chunk0.mp4\" 1\n"
"\"/usr/local/movies//chunk1.mp4\" 1\n"
"\"/usr/local/movies//chunk2.mp4\" 1\n"
"\"/usr/local/movies//chunk3.mp4\" 5\n"
"\"/usr/local/movies//chunk4.mp4\" 5\n";
/* define file handle */
FILE *output;
/* open the file */
output = fopen(filepath, "wb");
if(output == NULL) return -1; /* fopen failed */
/* write the lines */
fputs(output_lines, output);
/* close the file */
fclose(output);
return 0;
}
This version retrieves the text line given as argument to the program and then writes it to desired file:
#include <stdio.h>
int main(int argc, char *argv[])
{
if(argv[1] == NULL) return -1; /* no arguments, bail out */
/* where to write */
const char filepath[] =
"/var/streaming/playlists/chunkcombined/chunkcombined.playlist";
/* define file handle */
FILE *output;
/* open the file */
output = fopen(filepath, "wb"); /* change "wb" to "ab" for append mode */
if(output == NULL) return -1; /* fopen failed */
/* write the lines */
fputs(argv[1], output);
putc('\n', output);
/* close the file */
fclose(output);
return 0;
}
Example:
./write "\"Hello, World!\""
writes: "Hello, World!"
to:
/var/streaming/playlists/chunkcombined/chunkcombined.playlist.
I have some gzipped files that I want to read in C via fopen and fscanf. Is there anyway to do this without having to gunzip the files to temporary files?
Thanks.
You can use libzlib to open the gzipped files directly.
It also offers a "gzopen" function that behaves similar to fopen but operates on gzipped files. However, fscanf would probably not work on such a handle, since it expects normal FILE pointers.
If popen is fair game, you can do it with fopen and fscanf:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[])
{
const char prefix[] = "zcat ";
const char *arg;
char *cmd;
FILE *in;
char buf[4096];
if (argc != 2) {
fprintf(stderr, "Usage: %s file\n", argv[0]);
return 1;
}
arg = argv[1];
cmd = malloc(sizeof(prefix) + strlen(arg) + 1);
if (!cmd) {
fprintf(stderr, "%s: malloc: %s\n", argv[0], strerror(errno));
return 1;
}
sprintf(cmd, "%s%s", prefix, arg);
in = popen(cmd, "r");
if (!in) {
fprintf(stderr, "%s: popen: %s\n", argv[0], strerror(errno));
return 1;
}
while (fscanf(in, "%s", buf) == 1)
printf("%s: got [%s]\n", argv[0], buf);
if (ferror(in)) {
fprintf(stderr, "%s: fread: %s\n", argv[0], strerror(errno));
return 1;
}
else if (!feof(in)) {
fprintf(stderr, "%s: %s: unconsumed input\n", argv[0], argv[1]);
return 1;
}
return 0;
}
For example:
$ zcat file.gz
Every good boy does fine.
$ ./gzread file.gz
./gzread: got [Every]
./gzread: got [good]
./gzread: got [boy]
./gzread: got [does]
./gzread: got [fine.]
Do not use
sprintf(cmd, "zcat %s", argv[1]);
popen(cmd,"r");
to open .gz files. Properly escape argv[1] instead. You may otherwise end up with a vulnerability, especially when some injects an argument argv[1] such as
123;rm -rf /
It already helps to change the above instruction into
sprintf(cmd, "zcat \'%s\'",argv[1]);
You may also want to escape characters such as '\0', '\'', '\;' etc.
Newbie attempt at gzscanf():
#include <stdio.h>
#include <stdarg.h>
#include <zlib.h>
#define MAXLEN 256
int gzscanf(gzFile *stream, const char *fmt, ...) {
/* read one line from stream (up to newline) and parse with sscanf */
va_list args;
va_start(args, fmt);
int n;
static char buf[MAXLEN];
if (NULL == gzgets(stream, buf, MAXLEN)) {
printf("gzscanf: Failed to read line from gz file.\n");
exit(EXIT_FAILURE);
}
n = vsscanf(buf, fmt, args);
va_end(args);
return n;
}
You can use zlib and wrap it to a regular file pointer, this way you can use fscanf,fread,etc. transparently.
FILE *myfopen(const char *path, const char *mode)
{
#ifdef WITH_ZLIB
gzFile *zfp;
/* try gzopen */
zfp = gzopen(path,mode);
if (zfp == NULL)
return fopen(path,mode);
/* open file pointer */
return funopen(zfp,
(int(*)(void*,char*,int))gzread,
(int(*)(void*,const char*,int))gzwrite,
(fpos_t(*)(void*,fpos_t,int))gzseek,
(int(*)(void*))gzclose);
#else
return fopen(path,mode);
#endif
}
You can use zlib, but it will require you to replace your I/O calls to be zlib-specific.
you have to open a pipe to do this. The basic flow in pseudo code is:
create pipe // man pipe
fork // man fork
if (parent) {
close the writing end of the pipe // man 2 close
read from the pipe // man 2 read
} else if (child) {
close the reading end of the pipe // man 2 close
overwrite the file descriptor for stdout with the writing end of the pipe // man dup2
call exec() with gzip and the relevant parameters // man 3 exec
}
You can use the man pages in the comments for more details on how to do this.
It's quite simple to use zlib to open .gz files. There's a reasonable manual over at zlib.net.
Here's a quick example to get you started:
#include <stdio.h>
#include <zlib.h>
int main( int argc, char **argv )
{
// we're reading 2 text lines, and a binary blob from the given file
char line1[1024];
char line2[1024];
int blob[64];
if (argc > 1)
{
const char *filename = argv[1];
gzFile gz_in = gzopen( filename, "rb" ); // same as fopen()
if (gz_in != NULL)
{
if ( gzgets( gz_in, line1, sizeof(line1) ) != NULL ) // same as fgets()
{
if ( gzgets( gz_in, line2, sizeof(line2) ) != NULL )
{
if ( gzfread( blob, sizeof(int), 64, gz_in ) == 64 ) // same as fread()
{
printf("Line1: %s", line1);
printf("Line2: %s", line2);
// ...etc
}
}
}
gzclose(gz_in); // same as fclose()
}
else
{
printf( "Failed to GZ-open [%s]\n", filename );
}
}
return 0;
}
Remember to link with zlib, under UNIX gcc ... -lz