I want to transfer a file via a socket in linux system. I know how to use fgetc() and EOF to do so, or first get the length of file. Is there any other option?
Check for the return value of fread(). If the return value is not equal to the 3rd parameter passed into fread(), either error happens or EOF is reached.
Function fread() reads data from the given data stream(4th parameter) to an array pointed in to by a pointer(1st parameter)
fread (pointer to the block of memory, size of an element, number of elements, pointer to the input file)
fread() reads from where it left off last time and returns the number of elements successfully read. So if u do as below fread() will not go beyond that.
*You have to edit the number of elements according to the input file.
// Open input file
FILE *inptr = fopen (infile, "r");
//Check for a valid file
if (inptr == NULL)
{
fprintf (stderr, "Could notopen %s", infile);
return 1;
}
// Memory allocation for buffer
int *buffer = malloc(512);
// Read input file
while (fread (&buffer, 1, 512, inptr) == 512)
{
// DO WHAT YOU NEED HERE
}
// Free memory from buffer
free(buffer);
// close infile
fclose(inptr);
return 0;
Related
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *fp;
fp = fopen("clients.dat", "wb");
fclose(fp);
fp = fopen("clients.dat", "rb");
while (1) {
if (fp == EOF)
break;
else
printf("There is something inside a file");
}
fclose(fp);
return 0;
}
Here comes a question: what do empty binary files contain? should the pointer point to the EOF character? I mean: isn't it that the first and last thing in the file is EOF? OR how Can I check whether a file is empty or not?
An empty file contains nothing, it is empty. So it contains 0 bytes. EOF is not a character that is at the end of a file, it is an integer constant used as return value from some of the standard methods reading from a file to indicate end of file or some sort of error.
When you open a file you get a pointer to a FILE type back, this is what you can expect even from an empty file.
A file is not terminated the same way a string is, so there is no equivalent of a NULL character in a file, that determines when the file contents stops.
To determine whether a file you have opened and have a valid FILE pointer to is empty you can use fseek and ftell:
fseek(fp, 0, SEEK_END);
size = ftell(fp);
if (size == 0) {
// File is empty
}
Function fopen returns a pointer to a file handle of type FILE, not a pointer to any content of the file or a pointer to an EOF-character. The pointer is NULL if the file could not be opened at all, but does not indicate whether the file is empty or not.
To check if a file is empty you either (1) need to make an attempt to read bytes and handle the various results, or (2) to use fseek and ftell to move the read pointer to the end and ask then for the position.
(1)
fp=fopen("clients.dat","rb");
char buffer;
size_t bytesRead = fread(&buffer, 1, 1, fp); // try to read one byte
if(bytesRead == 1) {
printf("file contains at least one byte\n");
} else { // error handling
if (feof(fp))
printf("Attemt to read though end of file has been reached. File is empty.\n");
else if (ferror(fp)) {
perror("Error reading file.");
}
}
(2)
fp=fopen("clients.dat","rb");
fseek(fp, 0L, SEEK_END);
long size = ftell(fp);
if (size==0) {
// file is empty.
}
I'd prefer the second variant.
Here's another approach:
To check if the file is empty, you can simply read the file:
int c = fgetc(fp);
if (c == EOF)
{
// The file is empty or an error occured
if (feof(fp))
{
// Empty
}
else
{
// Error during file read
}
}
else
{
// non-empty file
}
Here comes a question what empty binary files contain ?
Empty files contain nothing, that is what makes them empty.
Regular files have a size which is not part of their data, but instead is normally a part of the directory entry or inode.
should the pointer point to the EOF character ?
No
First of all the pointer returned by fopen is NOT a pointer to the content of the file, but merely a pointer to a data structure describing the open file.
Secondly EOF is not an actual part of the file, but a special return value from the getc family of functions used to indicate that the end of file has been reached.
To test whether you are at the end of a file without reading from it you can use the feof function.
I am trying to read 128KB binary file in chunks of 256 Bytes. The first 20-40 bytes of 256 bytes seems to be always correct. However after that the data gets corrupted. I tried reading the file and writing it into another binary file and compared. More than half of the data is corrupted. Here is my code
uint8_t buffer[256]
read_bin_file = fopen("vtest.bin", "r");
if (read_bin_file == NULL)
{
printf("Unable to open file\n");
return false;
}
test_bin = fopen("test_file.bin", "w");
if (test_file == NULL)
{
printf("Unable to open file\n");
return false;
}
fflush(stdout);
for (i = 0; i <=0x1FF; i++)
{
file_Read_pointer = i * 256;
fseek(read_bin_file, file_Read_pointer, SEEK_SET);
fread(buffer, 256, 1, read_bin_file);
fseek(test_file, file_Read_pointer, SEEK_SET);
fwrite(buffer, 256, 1, test_file);
}
What is that I am missing?
Also when i try to increase the bytes read from 256 to 1024 ( i<0x7F) the error seems to decrease significantly. The file is almost 90% matching
If it is binary data you're reading and writing, then you should open the files in binary mode with read_bin_file = fopen("vtest.bin", "rb");. Note the "b" in the mode. This prevents special handling of new line characters.
Your fseeks are also unnecessary, the fread and fwrite calls will handle that for you.
From here "The file position indicator for the stream is advanced by the number of characters read."
I consider reading file of unknown size that I know doesn't change size in the meantime. So I intend to use fstat() function and struct stat. Now I am considering what the st_size field really means and how should I use it.
If I get the file size's in this way, then allocate a buffer of that size and read exactly that size of bytes there seems to be one byte left over. I come to this conclusion when I used feof() function to check if there really nothing left in FILE *. It returns false! So I need to read (st_size + 1) and only than all bytes have been read and feof() works correctly. Should I always add this +1 value to this size to read all bytes from binary file or there is some hidden reason that this isn't reading to EOF?
struct stat finfo;
fstat(fileno(fp), &finfo);
data_length = finfo.st_size;
I am asking about this because when I add +1 then the number of bytes read by fread() is really -1 byte less, and as the last byte is inserted 00 byte. I could also before checking with feof() do something like this
fread(NULL, 1, 1, fp);
It is the real code, it is a little odd situation:
// reading png bytes from file
FILE *fp = fopen("./test/resources/RGBA_8bits.png", "rb");
// get file size from file info
struct stat finfo;
fstat(fileno(fp), &finfo);
pngDataLength = finfo.st_size;
pngData = malloc(sizeof(unsigned char)*pngDataLength);
if( fread(pngData, 1, pngDataLength, fp) != pngDataLength) {
fprintf(stderr, "%s: Incorrect number of bytes read from file!\n", __func__);
fclose(fp);
free(pngData);
return;
}
fread(NULL, 1, 1, fp);
if(!feof(fp)) {
fprintf(stderr, "%s: Not the whole binary file has been read.\n", __func__);
fclose(fp);
free(pngData);
return;
}
fclose(fp);
This behaviour is normal.
feof will return true only once you have tried to read beyond the file's end which you don't do as you read exactly the size of the file.
I have written a function as follows to read a text file and write the content into another text file with a different file name:
The read file function:
char *getFileContent (const char *fileName)
{
char errorBuffer[50];
//Prepare read file
FILE *pReadFile;
long bufferReadSize;
char *bufferReadFile; //This variable is going to be returned as file content
size_t readFileSize;
pReadFile = fopen (fileName, "rb");
if (pReadFile != NULL)
{
// Get file size.
fseek (pReadFile , 0 , SEEK_END);
bufferReadSize = ftell (pReadFile);
rewind (pReadFile);
// Allocate RAM to contain the whole file:
bufferReadFile = (char*) malloc (sizeof(char) * bufferReadSize);
if (bufferReadFile != NULL)
{
// Copy the file into the buffer:
readFileSize = fread (bufferReadFile, sizeof(char), bufferReadSize, pReadFile);
if (readFileSize == bufferReadSize)
{
return bufferReadFile;
fclose (pReadFile);
free (bufferReadFile);
} else {
//fread failed
sprintf (errorBuffer, "File reading failed for file:\n%s", fileName);
MessageBox (NULL, errorBuffer, "Error file reading", MB_ICONERROR | MB_OK);
}
} else {
//malloc failed
sprintf (errorBuffer, "Memory allocation failed for file:\n%s", fileName);
MessageBox (NULL, errorBuffer, "Error memory allocation", MB_ICONERROR | MB_OK);
}
} else {
//fopen failed
sprintf (errorBuffer, "File opening failed for file:\n%s", fileName);
MessageBox (NULL, errorBuffer, "Error file opening", MB_ICONERROR | MB_OK);
}
}
The write file code:
//Get file content from read file
char *fileContent = getFileContent (readFileName);
FILE *pWriteFile = fopen (writeFileName, "wb");
fwrite (fileContent, sizeof (char), strlen (fileContent), pWriteFile);
fclose (pWriteFile);
They successfully work together to read and write files. However, in the written file, at the end of it, some strange characters come out like this:
ýýýý««««««««îþîþîþ
Please kindly help me solve this problem. How can I avoid the final strange characters in the written file when they were not there in the original file?
fwrite (fileContent, sizeof (char), strlen (fileContent), pWriteFile);
strlen() doesn't work here because fileContent contains binary data. The binary data could contain a null byte which would mean strlen() would be too short, or it may not contain a null byte which means strlen() would read past fileContent until it finds a null byte. This would be a reason why you see garbage at the end.
Note also, in your read routine, that the fclose() and the free() never happen because they come after the return statement. But, note that you can't free() the data until after you write it.
On the other hand, if it's not a binary file, all you need is a terminating 0 at the end of the data and then strlen() would work. So in your read, you need to alloc another byte and make sure that byte is zero:
bufferReadFile = (char*) malloc (sizeof(char) * bufferReadSize + 1); // note the + 1
bufferReadFile[bufferReadSize] = 0; // the terminating null byte.
I am reaing from a file, and when i read, it takes it line by line, and prints it
what i want exactly is i want an array of char holding all the chars in the file and print it once,
this is the code i have
if(strcmp(str[0],"#")==0)
{
FILE *filecomand;
//char fname[40];
char line[100];
int lcount;
///* Read in the filename */
//printf("Enter the name of a ascii file: ");
//fgets(History.txt, sizeof(fname), stdin);
/* Open the file. If NULL is returned there was an error */
if((filecomand = fopen(str[1], "r")) == NULL)
{
printf("Error Opening File.\n");
//exit(1);
}
lcount=0;
int i=0;
while( fgets(line, sizeof(line), filecomand) != NULL ) {
/* Get each line from the infile */
//lcount++;
/* print the line number and data */
//printf("%s", line);
}
fclose(filecomand); /* Close the file */
You need to determine the size of the file. Once you have that, you can allocate an array large enough and read it in a single go.
There are two ways to determine the size of the file.
Using fstat:
struct stat stbuffer;
if (fstat(fileno(filecommand), &stbuffer) != -1)
{
// file size is in stbuffer.st_size;
}
With fseek and ftell:
if (fseek(fp, 0, SEEK_END) == 0)
{
long size = ftell(fp)
if (size != -1)
{
// succesfully got size
}
// Go back to start of file
fseek(fp, 0, SEEK_SET);
}
Another solution would be to map the entire file to the memory and then treat it as a char array.
Under windows MapViewOfFile, and under unix mmap.
Once you mapped the file (plenty of examples), you get a pointer to the file's beginning in the memory. Cast it to char[].
Since you can't assume how big the file is, you need to determine the size and then dynamically allocate a buffer.
I won't post the code, but here's the general scheme. Use fseek() to navigate to the end of file, ftell() to get size of the file, and fseek() again to move the start of the file. Allocate a char buffer with malloc() using the size you found. The use fread() to read the file into the buffer. When you are done with the buffer, free() it.
Use a different open. i.e.
fd = open(str[1], O_RDONLY|O_BINARY) /* O_BINARY for MS */
The read statement would be for a buffer of bytes.
count = read(fd,buf, bytecount)
This will do a binary open and read on the file.