Read file into memory? - c

I can seem to only read file into memory if I explicitly declare the buffer size. This works
#include <stdio.h>
int main(){
FILE *fp = fopen("test.log", "rb");
char buffer[37];
fread(buffer, 1, 36, fp);
printf("%s", buffer);
}
This will add junk to the output
#include <stdio.h>
int main(){
FILE *fp = fopen("test.log", "rb");
fseek(fp, 0, SEEK_END);
long siz = ftell(fp);
rewind(fp);
char buffer[siz + 1];
fread(buffer, 1, siz, fp);
printf("%s", buffer);
}

insert buffer[siz]='\0'; before printf("%s", buffer);

Try a different approach - use a "memory map". What it does is it allows you to access the file as if it was a memory block. This can dramatically improve performance while simplifying your code at the same time.
Read more about it at http://en.wikipedia.org/wiki/Mmap

Related

Problam with fread in C

I tried to read binary files into dinamic string and somthing go wrong.
I cant set free the string and i cant print or do anything else with it.
The files are OK if I just open it without all the dinamic stuff it runs well.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma warning (disable: 4996)
#define STR_LEN 50
int main(int args, char** argv)
{
char filePath[STR_LEN];
char signaturePath[STR_LEN];
FILE* file;
FILE* signature;
int fileSize;
int signatureSize;
strcpy(filePath, argv[2]);
strcpy(signaturePath, argv[1]);
file = fopen(filePath, "rb");
signature = fopen(signaturePath, "rb");
if (file == NULL)
printf("e: f\n");
if (signature == NULL)
printf("e: s\n");
fseek(file, 0L, SEEK_END);
fileSize = ftell(file);
fseek(file, 0L, SEEK_SET);
fseek(signature, 0L, SEEK_END);
signatureSize = ftell(signature);
fseek(signature, 0L, SEEK_SET);
char* fileStr = (char)malloc(sizeof(char) * fileSize + 1);
char* signatureStr = (char)malloc(sizeof(char) * signatureSize + 1);
fread(fileStr, fileSize, 1, file);
fread(signatureStr, signatureSize, 1, signature);
free(fileStr);
free(signatureStr);
fclose(file);
fclose(signature);
return 0;
}
You are casting the pointers that malloc() returns to char. In typical environment, char is 1-byte long while pointers are 4-byte or 8-byte long. The cast will truncate the pointers, turning them to some invalid value.
Casting results of malloc() family is considered as a bad practice. Remove the harmful casts to fix.

C not reading entire BMP file - fopen

So I am trying to read a .bmp file in C. I am later going to encrypt the file using openssl libraries - but that's only background info.
I need to open the file in binary mode (obviously) but for whatever reason when I try to open the file, it only reads in 4 bytes. When I try to output this exact file I just opened (for error testing) it outputs the following - 88 24 AD FB.
In my troubleshooting I decided to try this on a text file (54 bytes) and I get the exact same result.
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(){
char * fileName="pic_original.bmp";
//read the file from given filename in binary mode
printf("Start to read the .bmp file \n");
FILE *image;
image = fopen(fileName,"rb");
//print the size of the image (4 bytes every damn time)
printf("Size of image: %d\n",sizeof(image));
//output the exact file that was read (error testing)
FILE *test;
test = fopen("./test.bin", "w");
fwrite(image, sizeof(image), 1, test);
fclose(test);
fclose(image);
return 1;
}
This is the image (uploaded as png for some reason)
Not exactly sure where I'm going wrong here but I'm not very seasoned in C.
Cheers,
Liam
EDIT 1:
//allocate memory for the header and image
char *headerBuf = (char *)malloc(54);
char *imageBuf = (char *)malloc(sizeof(image)-54); //this line is wrong - thanks to user EOF
//allocate memory for the final ciphertext
char *imagecipherCBC = (char *)malloc(sizeof(image)); //wrong also
//read first 54 bytes (header)
rewind(image);
fread(headerBuf,54,1,image);
//read the bitmap image until the end of the file
fread(imageBuf,sizeof(image),1,image); //also wrong
Well,
The size of the image is of course, 4 bytes which is a file pointer on a 32 bit machine.
I think you have to prepare some image buffer of your bmp file as a simple example, then you can do encrypt and decrypt the contents of this image buffer if your file is not too big.
static void read_from_image(char *imageBuf, int fileLength)
{
const char * outFileName="c:/DEV/temp/test.bin";
char headerBuf[54];
char *imagecipherCBC;
FILE *test;
test = fopen(outFileName, "wb");
//allocate memory for the final ciphertext
imagecipherCBC = (char *)malloc(fileLength *sizeof(char));
//read first 54 bytes (header)
//fread(headerBuf,54,1,image);
memcpy(headerBuf, imageBuf, 54 * sizeof(char));
//read the bitmap image until the end of the file
//fread(imageBuf,sizeof(image),1,image); //also wrong
fwrite(imageBuf, fileLength * sizeof(char), 1, test);
fflush(test);
fclose(test);
free(imagecipherCBC),imagecipherCBC = NULL;
free(imageBuf),imageBuf = NULL;
return;
}
You can have a file length and an image buffer in a main function.
int main(int argc, char *argv[])
{
const char * fileName="c:/DEV/temp/pic_original.bmp";
int fileLength = 0;
FILE *image;
char *imageBuffer;
imageBuffer = NULL;
image = fopen(fileName,"rb");
printf("read the file from given filename in binary mode \n");
printf("Start to read the .bmp file \n");
//try to get a file length;
fseek(image, 0, SEEK_END);
fileLength = ftell(image);
fseek(image, 0, SEEK_SET);
rewind(image);
imageBuffer = (char*)malloc(fileLength * sizeof(char));
//print the size of the image (4 bytes every damn time)
printf("read the file from given filename in binary mode \n");
printf("Size of image file pointer: %d\n",sizeof(image));
printf("Size of image: %d\n",fileLength);
//output the exact file that was read (error testing)
fread(imageBuffer,sizeof(char),fileLength*sizeof(char), image);
fclose(image);
read_from_image(imageBuffer, fileLength);
return 0;
}
good luck
If your goal is to encrypt the file then read the entire file in to buffer, encrypt it, and save it as binary. You can find the file size by moving the file pointer to the end. Example:
int main()
{
FILE *fin;
fin = fopen("pic_original.bmp", "rb");
fseek(fin, 0, SEEK_END);
int filesize = ftell(fin);
rewind(fin);
char *buf = malloc(filesize);
fread(buf, 1, filesize, fin);
fclose(fin);
//encrypt the buffer...
FILE *fout = fopen("output.bmp", "wb");
fwrite(buf, 1, filesize, fout);
fclose(fout);
return 0;
}
This will work with any file. OpenSSL already has functions to encrypt files directly.
If for some reason you want to keep the header the same, and only change the bits which follow, then read the header separately:
int main()
{
FILE *fin = fopen("input.bmp", "rb");
if(!fin) { printf("cannot open input\n"); return 0; }
FILE *fout = fopen("output.bmp", "wb");
if(!fout) { printf("cannot open output\n"); return 0; }
fseek(fin, 0, SEEK_END);
int filesize = ftell(fin);
if(filesize <= 54)
{
printf("wrong filesize\n");
return 0;
}
rewind(fin);
char *header = malloc(54);
char *buf = malloc(filesize - 54);
//encrypt buf...
fread(header, 1, 54, fin);
fread(buf, 1, filesize - 54, fin);
fclose(fin);
fwrite(header, 1, 54, fout);
fwrite(buf, 1, filesize - 54, fout);
fclose(fout);
free(header);
free(buf);
return 0;
}
I suppose this has the advantage that encrypted bitmap will still be recognized as a bitmap. But only encryption methods does not add extra bytes to the output.
Note that 8-bit, 4-bit and monochrome bitmaps have a palette which come after the 54 byte heading, then comes the image bits.

Reading a text file in C

I am reading a text file and trying to display its contents on the console. Here is my code:
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <fstream>
int main()
{
FILE* fp=NULL;
char buff[100];
fp=fopen("myfile.txt","r");
if(fp==NULL)
{
printf("Couldn't Open the File!!!\n");
}
fseek(fp, 0, SEEK_END);
size_t file_size = ftell(fp);
fread(buff,file_size,1,fp);
printf("Data Read [%s]",buff);
fclose(fp);
return 0;
}
but only redundant data is being displayed on the console; could someone please point out my mistake?
You forgot to reset the file pointer to start after doing this.
fseek(fp, 0, SEEK_END);
Do this after finding size (file_size).
rewind (fp);
You need to seek back to the start of the file before reading:
int main()
{
FILE* fp=NULL;
char buff[100];
fp=fopen("myfile.txt","r");
if(fp==NULL)
{
printf("Couldn't Open the File!!!\n");
exit(1); // <<< handle fopen failure
}
fseek(fp, 0, SEEK_END);
size_t file_size = ftell(fp);
fseek(fp, 0, SEEK_SET); // <<< seek to start of file
fread(buff,file_size,1,fp);
printf("Data Read [%s]",buff);
fclose(fp);
return 0;
}
Try it....
#include <stdio.h>
#include <stdlib.h>
void handle_line(char *line) {
printf("%s", line);
}
int main(int argc, char *argv[]) {
int size = 1024, pos;
int c;
char *buffer = (char *)malloc(size);
FILE *f = fopen("myfile.txt", "r");
if(f) {
do { // read all lines in file
pos = 0;
do{ // read one line
c = fgetc(f);
if(c != EOF) buffer[pos++] = (char)c;
if(pos >= size - 1) { // increase buffer length - leave room for 0
size *=2;
buffer = (char*)realloc(buffer, size);
}
}while(c != EOF && c != '\n');
buffer[pos] = 0;
// line is now in buffer
handle_line(buffer);
} while(c != EOF);
fclose(f);
}
free(buffer);
return 0;
}
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <fstream>
int main()
{
FILE* fp=NULL;
char *buff; //change array to pointer
fp=fopen("myfile.txt","r");
if(fp==NULL)
{
printf("Couldn't Open the File!!!\n");
}
fseek(fp, 0, SEEK_END);
size_t file_size = ftell(fp);
buff = malloc(file_size); //allocating memory needed for reading file data
fseek(fp,0,SEEK_SET); //changing fp to point start of file data
fread(buff,file_size,1,fp);
printf("Data Read [%s]",buff);
fclose(fp);
return 0;
}
having a buffer of 100 bytes to read a file is not a better idea as since the file size may be more than 100 bytes.
A better file io can be done by doing a fgets on the file, if its not a type of metadata that you wanted to read using the fread.
fgets in a while loop can be used to check whether its reached EOF or a feof call can be used to check the EOF.
a sample code listing of fgets can be like this:
while (fgets(buf, len, fp)) {
printf("%s", buf);
}
or a sample that is used with fgets can be like this:
while (fread(buf, len, 1, fp) >= 0) {
printf("%s\n", buf);
}

fread() isn't writing to the buffer

#include <Windows.h>
#include <stdio.h>
int count = 0;
FILE* pFile = 0;
long Size = 0;
void *memfrob(void * s, size_t n)
{
char *p = (char *) s;
while (n-- > 0)
*p++ ^= 42;
return s;
}
int main()
{
fopen_s(&pFile, "***", "r+");
fseek(pFile, 0, SEEK_END);
Size = ftell(pFile);
char *buffer = (char*)malloc(Size);
memset(buffer, 0, Size);
fread(buffer, Size, 1, pFile);
fclose(pFile);
memfrob(buffer, Size);
fopen_s(&pFile, "***", "w+");
fwrite(buffer, Size, 1, pFile);
fclose(pFile);
}
Hi, fread isn't reading anything from file to buffer and I can't figure out why. Could someone give me a hint or a push in the right direction?
You need to seek back to the beginning of the file before you fread.
You did a fseek to the end of the file and didn't fseek back before you did the fread.

Changing one byte in a file in C

I have a file stream open and ready.
How do I access and change a single Byte in the stream such that the change is reflected on the file?
Any suggestions?
#include "stdio.h"
int main(void)
{
FILE* f = fopen("so-data.dat", "r+b"); // Error checking omitted
fseek(f, 5, SEEK_SET);
fwrite("x", 1, 1, f);
fclose(f);
}
FILE* fileHandle = fopen("filename", "r+b"); // r+ if you need char mode
fseek(fileHandle, position_of_byte, SEEK_SET);
fwrite("R" /* the value to replace with */, 1, 1, fileHandle);
#include <stdio.h> /* standard header, use the angle brackets */
int main(void)
{
char somechar = 'x'; /* one-byte data */
FILE* fp = fopen("so-data.txt", "r+");
if (fp) {
fseek(fp, 5, SEEK_SET);
fwrite(&somechar, 1, 1, fp);
fclose(fp);
}
return 0; /* if you are on non-C99 systems */
}

Resources