On Ubuntu Linux I have written a c program based on the Libao example program to open audio wave file and play. It works fine but at the end after finish playing there is crackling high pitch noise. Here is the code which I modified mt libao example. How can I fix it? Please help
#include <stdio.h>
#include <string.h>
#include <ao/ao.h>
#include <math.h>
#define BUF_SIZE 4096
int main(int argc, char **argv)
{
ao_device *device;
ao_sample_format format;
int default_driver;
char *buffer;
int buf_size;
int sample;
FILE *fp;
float freq = 440.0;
int i;
/* -- Initialize -- */
fprintf(stderr, "libao example program\n");
ao_initialize();
/* -- Setup for default driver -- */
default_driver = ao_default_driver_id();
memset(&format, 0, sizeof(format));
format.bits = 16;
format.channels = 2;
format.rate = 44100;
format.byte_format = AO_FMT_LITTLE;
/* -- Open driver -- */
// device = ao_open_live(default_driver, &format, NULL /* no options */);
device = ao_open_live(default_driver, &format, NULL /* no options */);
if (device == NULL) {
fprintf(stderr, "Error opening device.\n");
return 1;
}
fp = fopen("nc.wav", "rb");
if (fp == NULL) {
fprintf(stderr, "Unable to open file \n");
return;
}
fseek(fp, 0, SEEK_END);
unsigned long fileLen = ftell(fp);
fseek(fp, 0, SEEK_SET);
//Allocate memory
buffer=(char *)malloc(fileLen+1);
if (!buffer)
{
fprintf(stderr, "Memory error!");
fclose(fp);
return;
}
fread(buffer, fileLen, 1, fp);
fclose(fp);
ao_play(device, buffer, buf_size);
/* -- Close and shutdown -- */
ao_close(device);
ao_shutdown();
return (0);
}
The buf_size variable is passed to ao_play without being initialized, and the crackles most likely occur because it is playing past the end of the sample buffer into random memory.
Depending on your compiler settings, the compiler can warn you about uninitialized variables bugs like this (gcc only does it when optimizations are turned on, via the -Wuninitialized or -Wall settings).
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 am trying to write some data into the file line by line and then reading each data separatly line by line from the source file and writing it to another file.
But while writing data to destination file , I am getting spaces.
I mean the data is being written after multiple spaces.
I am using fgets instead of fread.
/*
* ======== fatsd.c ========
*/
#include <file.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <third_party/fatfs/ffcio.h>
#include <ti/display/Display.h>
#include <ti/drivers/GPIO.h>
#include <ti/drivers/SDFatFS.h>
#include <ti/drivers/UART.h>
/* Example/Board Header files */
#include "Board.h"
/* Buffer size used for the file copy process */
#ifndef CPY_BUFF_SIZE
#define CPY_BUFF_SIZE 2048
#endif
/* String conversion macro */
#define STR_(n) #n
#define STR(n) STR_(n)
/* Drive number used for FatFs */
#define DRIVE_NUM 0
int i= 20;
int x;
char con_buff[100];
const char inputfile[] = "fat:"STR(DRIVE_NUM)":input1.txt";
const char outputfile[] = "fat:"STR(DRIVE_NUM)":output.txt";
const char copyfile[] = "fat:"STR(DRIVE_NUM)":copy2.txt";
char textarray[] = "Jan 1 2017 00:00:00 75 822 96 548 85 76 82 93 78 82 64 89";
char text[]="ram sham heloo bye";
char cpy[]="\r\n";
static Display_Handle display;
/* File name prefix for this filesystem for use with TI C RTS */
char fatfsPrefix[] = "fat";
//unsigned char cpy_buff[CPY_BUFF_SIZE + 1];
char cpy_buff[CPY_BUFF_SIZE + 1];
char mybuff[CPY_BUFF_SIZE + 1];
/*
* ======== mainThread ========
* Thread to perform a file copy
*
* Thread tries to open an existing file inputfile[]. If the file doesn't
* exist, create one and write some known content into it.
* The contents of the inputfile[] are then copied to an output file
* outputfile[]. Once completed, the contents of the output file are
* printed onto the system console (stdout).
*/
void *mainThread(void *arg0)
{
SDFatFS_Handle sdfatfsHandle;
/* Variables for the CIO functions */
FILE *src, *dst,*new;
/* Variables to keep track of the file copy progress */
unsigned int bytesRead = 0;
unsigned int bytesWritten = 0;
unsigned int filesize;
unsigned int totalBytesCopied = 0;
/* Call driver init functions */
GPIO_init();
SDFatFS_init();
/* Configure the LED pin */
GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
/* add_device() should be called once and is used for all media types */
add_device(fatfsPrefix, _MSA, ffcio_open, ffcio_close, ffcio_read,
ffcio_write, ffcio_lseek, ffcio_unlink, ffcio_rename);
/* Turn on user LED */
GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);
strcpy(con_buff,"This example requires a FAT filesystem on the SD card.\r\n"
"You will get errors if your SD card is not formatted with a filesystem.\r\n");
puts(con_buff);
/* Mount and register the SD Card */
sdfatfsHandle = SDFatFS_open(Board_SDFatFS0, DRIVE_NUM);
if (sdfatfsHandle == NULL)
{
strcpy(con_buff,"Error starting the SD card\n");
puts(con_buff);
x=1;
while (1);
}
else
{
strcpy(con_buff,"Drive is mounted\n");
x=2;
}
/* Try to open the source file */
src = fopen(inputfile, "a");
if (!src)
{
strcpy(con_buff,"Creating a new file ...");
puts(con_buff);
x=3;
/* Open file for both reading and writing */
src = fopen(inputfile, "w+");
if (!src)
{
strcpy(con_buff,"Error:could not be created.\nPlease check the Board.html if additional jumpers are necessary.check if sd card is inserted correctly\n"
"Aborting... \n");
puts(con_buff);
x=4;
while (1);
}
x=5;
/* Reset the internal file pointer */
rewind(src);
}
else {
fseek(src, 0, SEEK_END);
filesize = ftell(src);
if(filesize!=0)
{
fwrite(cpy, 1, strlen(cpy), src);
}
fwrite(textarray, 1, strlen(textarray), src);
fwrite(cpy, 1, strlen(cpy), src);
fwrite(text, 1, strlen(text), src);
fwrite(cpy, 1, strlen(cpy), src);
fwrite(textarray, 1, strlen(textarray), src);
fwrite(cpy, 1, strlen(cpy), src);
fwrite(text, 1, strlen(text), src);
x=6;
}
fflush(src);
fclose(src);
/* Create a new file object for the file copy */
dst = fopen(outputfile, "w");
new = fopen(copyfile, "a");
src = fopen(inputfile, "r");
if(!new)
{
strcpy(con_buff,"Error opening new file ");
puts(con_buff);
}
if (!dst)
{
strcpy(con_buff,"Error opening \"%s\"\n"
"Aborting...\n");
puts(con_buff);
x=7;
while (1);
}
else {
strcpy(con_buff,"Starting file copy\n");
puts(con_buff);
x=8;
}
/* Copy the contents from the src to the dst */
while (!feof(src))
{
fgets(cpy_buff,sizeof(cpy_buff),src); //READ FROM FILE
/* Read from source file */
puts(cpy_buff);
i=i+1;
fwrite(cpy_buff, 1,sizeof(cpy_buff),dst); //PUBLISH
strcpy(cpy_buff,"\0");
}
fflush(dst);
/* Get the filesize of the source file */
fseek(src, 0, SEEK_END);
filesize = ftell(src);
sprintf(con_buff,"size of file is %d",filesize);
puts(con_buff);
/* Close both inputfile[] and outputfile[] */
fclose(src);
fclose(dst);
fclose(new);
sprintf(con_buff,"File \"%s\" (%u B) copied to \"%s\" (Wrote %u B)\n",inputfile, filesize, outputfile, totalBytesCopied);
puts(con_buff);
/* Now output the outputfile[] contents onto the console */
/* Stopping the SDCard */
SDFatFS_close(sdfatfsHandle);
sprintf(con_buff,"Drive %u unmounted\n", DRIVE_NUM);
puts(con_buff);
return (NULL);
}
/*
* ======== fatfs_getFatTime ========
*/
int32_t fatfs_getFatTime(void)
{
/*
* FatFs uses this API to get the current time in FatTime format. User's
* must implement this function based on their system's timekeeping
* mechanism. See FatFs documentation for details on FatTime format.
*/
/* Jan 1 2017 00:00:00 */
return (0x4A210000);
}
regarding statements like:
fwrite(cpy_buff, 1,sizeof(cpy_buff),dst);
This will write the whole buffer, even though most of the trailing bytes of the buffer cpy_buff are garbage. Suggest:
fwrite(cpy_buff, 1,strlen(cpy_buff),dst);
I'm trying to send .amr files from my desktop to a SIM900 GSM module over UART.
I'm using teuniz's RS232 library.
I do the initialisation using AT commands and then read the file into a buffer and write it to the UART using the RS232_SendByte() library function byte-by-byte, but it doesn't seem to work.
I send the following AT commands:
AT+CFSINIT
AT+CFSWFILE=\"audio.amr\",0,6694,13000 # After which I get the CONNECT message from the SIM900 module
# Here's where I send the file
AT+CFSGFIS=\"audio.amr\"
Here's my code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "rs232.h"
char *readFile(char *filename, int *size) {
char *source = NULL;
FILE *fp = fopen(filename, "rb");
if (fp != NULL) {
/* Go to the end of the file. */
if (fseek(fp, 0L, SEEK_END) == 0) {
/* Get the size of the file. */
long bufsize = ftell(fp);
if (bufsize == -1) { return NULL; }
/* Allocate our buffer to that size. */
source = malloc(sizeof(char) * (bufsize + 1));
if(!source) return NULL;
/* Go back to the start of the file. */
if (fseek(fp, 0L, SEEK_SET) != 0) { return NULL; }
/* Read the entire file into memory. */
size_t newLen = fread(source, sizeof(char), bufsize, fp);
if ( ferror( fp ) != 0 ) {
fputs("Error reading file", stderr);
free(source);
return NULL;
} else {
source[newLen++] = 0; /* Just to be safe. */
}
*size = bufsize;
}
fclose(fp);
}
return source;
}
int main(int argc, char *argv[])
{
int ret = 0, cport_nr = 2, bdrate=38400;
char data[2000] = {0};
if(RS232_OpenComport(cport_nr, bdrate)) {
printf("Can not open comport\n");
ret = -1;
goto END;
}
int size;
unsigned char *filebuf = readFile("audio.amr", &size);
if (!filebuf) {
ret = -1;
goto END_1;
}
/* Initialization */
RS232_cputs(cport_nr, "AT");
RS232_cputs(cport_nr, "AT+CFSINIT");
sleep(1);
RS232_cputs(cport_nr, "AT+CFSWFILE=\"audio.amr\",0,6694,13000");
/* Wait for CONNECT */
sleep(2);
printf("Sending file of size: %d\n", size);
int i;
for (i = 0; i < size; ++i) {
putchar(filebuf[i]);
RS232_SendByte(cport_nr, filebuf[i]);
}
free(filebuf);
sleep(1);
/* Check if file transferred right */
RS232_cputs(cport_nr, "AT+CFSGFIS=\"audio.amr\"");
END_1:
RS232_CloseComport(cport_nr);
END:
return ret;
}
EDIT 1
Normally, the procedure to send a file to SIM900 using AT commands would be as documented here:
AT+CFSINIT # Initialize flash; Response is OK
AT+CFSWFILE=<filename>,<writeMode>,<fileSize>,<InputTime> # Write file with these parameter; Response is CONNECT; So this is when I start sending the file
Here's where I send the file. If it worked and the sent file size matched the <filesize> sent in the above command, SIM900 must respond with OK, which it doesn't. :(
AT+CFSGFIS=<filename> # Gives the file size on flash. This gives me an error since the file didn't upload correctly.
This leads me to beleive there's something wrong with my program. I'm reading the file in binary mode. And the size reported is exacty the same as I specify in the AT+CFSWFILE=<filename>,<writeMode>,<fileSize>,<InputTime> command.
I'm not good at C and I'm trying to do something simple. I want to open a binary file, read blocks of 1024 bytes of data and dump into a buffer, process the buffer, read another 1024 byes of data and keep doing this until EOF. I know how / what I want to do with the buffer, but it's the loop part and file I/O I keep getting stuck on.
PSEUDO code:
FILE *file;
unsigned char * buffer[1024];
fopen(myfile, "rb");
while (!EOF)
{
fread(buffer, 1024);
//do my processing with buffer;
//read next 1024 bytes in file, etc.... until end
}
fread() returns the number of bytes read. You can loop until that's 0.
FILE *file = NULL;
unsigned char buffer[1024]; // array of bytes, not pointers-to-bytes
size_t bytesRead = 0;
file = fopen(myfile, "rb");
if (file != NULL)
{
// read up to sizeof(buffer) bytes
while ((bytesRead = fread(buffer, 1, sizeof(buffer), file)) > 0)
{
// process bytesRead worth of data in buffer
}
}
#include <stdio.h>
#include <unistd.h> // For system calls write, read e close
#include <fcntl.h>
#define BUFFER_SIZE 1024
int main(int argc, char* argv[]) {
unsigned char buffer[BUFFER_SIZE] = {0};
ssize_t byte = 0;
int fd = open("example.txt", O_RDONLY);
while ((byte = read(fd, buffer, sizeof(buffer))) != 0) {
printf("%s", buffer);
memset(buffer, 0, BUFFER_SIZE);
}
close(fd);
return 0;
}
Edited code added
#include <stdio.h>
#include <unistd.h> // For system calls write, read e close
#include <fcntl.h>
#define BUFFER_SIZE 1024
int main(int argc, char* argv[]) {
unsigned char buffer[BUFFER_SIZE] = {0};
ssize_t byte = 0;
// open file in read mode
int fd = open("example.txt", O_RDONLY);
// file opening failure
if (fd == -1) {
printf("Failed to open file\n");
return -1;
}
// loop
while (1) {
// read buffer
byte = read(fd, buffer, sizeof(buffer));
// error
if (byte == -1) {
printf("Encountered an error\n");
break;
} else if (byte == 0) {
// file end exit loop
printf("File reading end\n");
break;
}
// printf file data
printf("%s", buffer);
memset(buffer, 0, BUFFER_SIZE);
}
// Close file
close(fd);
return 0;
}
This question already has answers here:
How do you determine the size of a file in C?
(15 answers)
Closed 3 years ago.
How can I find out the size of a file I opened with an application written in C ?
I would like to know the size, because I want to put the content of the loaded file into a string, which I allocate using malloc(). Just writing malloc(10000*sizeof(char)); is IMHO a bad idea.
You need to seek to the end of the file and then ask for the position:
fseek(fp, 0L, SEEK_END);
sz = ftell(fp);
You can then seek back, e.g.:
fseek(fp, 0L, SEEK_SET);
or (if seeking to go to the beginning)
rewind(fp);
Using standard library:
Assuming that your implementation meaningfully supports SEEK_END:
fseek(f, 0, SEEK_END); // seek to end of file
size = ftell(f); // get current file pointer
fseek(f, 0, SEEK_SET); // seek back to beginning of file
// proceed with allocating memory and reading the file
Linux/POSIX:
You can use stat (if you know the filename), or fstat (if you have the file descriptor).
Here is an example for stat:
#include <sys/stat.h>
struct stat st;
stat(filename, &st);
size = st.st_size;
Win32:
You can use GetFileSize or GetFileSizeEx.
If you have the file descriptor fstat() returns a stat structure which contain the file size.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
// fd = fileno(f); //if you have a stream (e.g. from fopen), not a file descriptor.
struct stat buf;
fstat(fd, &buf);
off_t size = buf.st_size;
I ended up just making a short and sweet fsize function(note, no error checking)
int fsize(FILE *fp){
int prev=ftell(fp);
fseek(fp, 0L, SEEK_END);
int sz=ftell(fp);
fseek(fp,prev,SEEK_SET); //go back to where we were
return sz;
}
It's kind of silly that the standard C library doesn't have such a function, but I can see why it'd be difficult as not every "file" has a size(for instance /dev/null)
How to use lseek/fseek/stat/fstat to get filesize ?
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
void
fseek_filesize(const char *filename)
{
FILE *fp = NULL;
long off;
fp = fopen(filename, "r");
if (fp == NULL)
{
printf("failed to fopen %s\n", filename);
exit(EXIT_FAILURE);
}
if (fseek(fp, 0, SEEK_END) == -1)
{
printf("failed to fseek %s\n", filename);
exit(EXIT_FAILURE);
}
off = ftell(fp);
if (off == -1)
{
printf("failed to ftell %s\n", filename);
exit(EXIT_FAILURE);
}
printf("[*] fseek_filesize - file: %s, size: %ld\n", filename, off);
if (fclose(fp) != 0)
{
printf("failed to fclose %s\n", filename);
exit(EXIT_FAILURE);
}
}
void
fstat_filesize(const char *filename)
{
int fd;
struct stat statbuf;
fd = open(filename, O_RDONLY, S_IRUSR | S_IRGRP);
if (fd == -1)
{
printf("failed to open %s\n", filename);
exit(EXIT_FAILURE);
}
if (fstat(fd, &statbuf) == -1)
{
printf("failed to fstat %s\n", filename);
exit(EXIT_FAILURE);
}
printf("[*] fstat_filesize - file: %s, size: %lld\n", filename, statbuf.st_size);
if (close(fd) == -1)
{
printf("failed to fclose %s\n", filename);
exit(EXIT_FAILURE);
}
}
void
stat_filesize(const char *filename)
{
struct stat statbuf;
if (stat(filename, &statbuf) == -1)
{
printf("failed to stat %s\n", filename);
exit(EXIT_FAILURE);
}
printf("[*] stat_filesize - file: %s, size: %lld\n", filename, statbuf.st_size);
}
void
seek_filesize(const char *filename)
{
int fd;
off_t off;
if (filename == NULL)
{
printf("invalid filename\n");
exit(EXIT_FAILURE);
}
fd = open(filename, O_RDONLY, S_IRUSR | S_IRGRP);
if (fd == -1)
{
printf("failed to open %s\n", filename);
exit(EXIT_FAILURE);
}
off = lseek(fd, 0, SEEK_END);
if (off == -1)
{
printf("failed to lseek %s\n", filename);
exit(EXIT_FAILURE);
}
printf("[*] seek_filesize - file: %s, size: %lld\n", filename, (long long) off);
if (close(fd) == -1)
{
printf("failed to close %s\n", filename);
exit(EXIT_FAILURE);
}
}
int
main(int argc, const char *argv[])
{
int i;
if (argc < 2)
{
printf("%s <file1> <file2>...\n", argv[0]);
exit(0);
}
for(i = 1; i < argc; i++)
{
seek_filesize(argv[i]);
stat_filesize(argv[i]);
fstat_filesize(argv[i]);
fseek_filesize(argv[i]);
}
return 0;
}
Have you considered not computing the file size and just growing the array if necessary? Here's an example (with error checking ommitted):
#define CHUNK 1024
/* Read the contents of a file into a buffer. Return the size of the file
* and set buf to point to a buffer allocated with malloc that contains
* the file contents.
*/
int read_file(FILE *fp, char **buf)
{
int n, np;
char *b, *b2;
n = CHUNK;
np = n;
b = malloc(sizeof(char)*n);
while ((r = fread(b, sizeof(char), CHUNK, fp)) > 0) {
n += r;
if (np - n < CHUNK) {
np *= 2; // buffer is too small, the next read could overflow!
b2 = malloc(np*sizeof(char));
memcpy(b2, b, n * sizeof(char));
free(b);
b = b2;
}
}
*buf = b;
return n;
}
This has the advantage of working even for streams in which it is impossible to get the file size (like stdin).
If you're on Linux, seriously consider just using the g_file_get_contents function from glib. It handles all the code for loading a file, allocating memory, and handling errors.
#include <stdio.h>
#define MAXNUMBER 1024
int main()
{
int i;
char a[MAXNUMBER];
FILE *fp = popen("du -b /bin/bash", "r");
while((a[i++] = getc(fp))!= 9)
;
a[i] ='\0';
printf(" a is %s\n", a);
pclose(fp);
return 0;
}
HTH