I'm getting only 4 bytes in my buffer when I try to read the whole file (weight a lot more than 4B). But when I'm reading a .txt file, I successfully recover the whole file content.
I've searched in the fopen man, in the malloc mand and in the fread man, but I cant' understand why.
char* readFile(char* path)
{
/*VARIABLES*/
FILE *inFile;
long inFileSize;
long readSize;
char *buffer = NULL;
/*OPEN FILES*/
inFile = fopen(path,"rb");
/*ERROR HANDLING : FILES*/
if(!inFile) {
return "";
}
/*GETTING FILE SIZE*/
fseek(inFile, 0, SEEK_END);
inFileSize = ftell(inFile);
rewind(inFile);
printf("The file is %ld bytes long\n",inFileSize);
/*ALLOCATING MEMORY*/
buffer = (char*) malloc(sizeof(char) * (inFileSize + 1) );
/*READ THE CONTENT AND PUT IT IN THE BUFFER*/
readSize = fread(buffer, sizeof(char), inFileSize, inFile);
/*ERROR HANDLING : readed size != to the file size*/
if (inFileSize != readSize)
{
printf("Freeing buffer\n");
free(buffer);
buffer = NULL;
}
/*ADDING THE END STRING CODE*/
buffer[inFileSize] = '\0';
/*CLOSE THE FILE*/
fclose(inFile);
return buffer;
}
Also, when I change the image extension from .jpeg to .txt, I still get 4 bytes only.
Can you help me ?
Related
I'm trying to read text from a file and store it into a string so that I can then encrypt and decrypt it using openssl. How can I do this?
You could use dynamic memory. My "skeleton" code for reading any type of file is this:
// Assumes: the file # file name is a text file; ASCII or UTF-8 (no BOM)
void readwholefile(char *filename)
{
FILE *fp;
char *buffer = NULL;
size_t i, len;
fp = fopen(filename, "rb");
fseek(fp, 0, SEEK_END);
len = ftell(fp);
rewind(fp);
buffer = malloc(len + 1);
if (NULL == buffer)
{
// Handle malloc failure & exit
exit(-1);
}
fread(buffer, 1, len, fp);
fclose(fp);
buffer[len] = '\0';
// buffer now contains the content of your file; do what you want with it
free(buffer);
buffer = NULL;
}
If you are using a POSIX system, you can use getline:
char *line = nullptr;
size_t line_size = 0
ssize_t len = getline(&line, &line_size, fp);
This will read until a newline and malloc enough space for the resulting line. You can use getdelim to read up to some delimiter other than a newline.
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.
How to read all the content which is stored into a txt file?
If I have a txt file with words in it and I want to read all of them and store them into a string how can I do it?
If I use fscanf(in, "%s", string) I only read the first word and when there is the first white space the fscanf stops its job. How can I read all of the words and store them in a string?
If you're asking how to slurp the entire contents of a file into a single buffer in memory, here's one way (assuming sufficient space in memory):
FILE *fp;
char *buffer = NULL;
size_t len, num_read;
fp = fopen("myfile", "r");
if(fp == NULL) // handle error...
{}
fseek(fp, 0, SEEK_END);
len = ftell(fp);
rewind(fp);
buffer = malloc(len + 1);
if(buffer == NULL) // handle error...
{}
num_read = fread(buffer, 1, len, fp);
fclose(fp);
buffer[num_read] = '\0';
// buffer now contains the entire content of your file
use(buffer);
free(buffer);
buffer = NULL;
I'm looking for a cross platform (Windows + Linux) solution to reading the contents of an entire file into a char *.
This is what I've got now:
FILE *stream;
char *contents;
fileSize = 0;
//Open the stream
stream = fopen(argv[1], "r");
//Steak to the end of the file to determine the file size
fseek(stream, 0L, SEEK_END);
fileSize = ftell(stream);
fseek(stream, 0L, SEEK_SET);
//Allocate enough memory (should I add 1 for the \0?)
contents = (char *)malloc(fileSize);
//Read the file
fscanf(stream, "%s", contents);
//Print it again for debugging
printf("Read %s\n", contents);
Unfortunately this will only print the first line in the file so I assume that fscanf stops at the first newline character. However I would like to read the entire file including, and preserving, the new line characters. I'd prefer not to use a while loop and realloc to manually construct the entire string, I mean there has to be a simpler way?
Something like this, may be?
FILE *stream;
char *contents;
fileSize = 0;
//Open the stream. Note "b" to avoid DOS/UNIX new line conversion.
stream = fopen(argv[1], "rb");
//Seek to the end of the file to determine the file size
fseek(stream, 0L, SEEK_END);
fileSize = ftell(stream);
fseek(stream, 0L, SEEK_SET);
//Allocate enough memory (add 1 for the \0, since fread won't add it)
contents = malloc(fileSize+1);
//Read the file
size_t size=fread(contents,1,fileSize,stream);
contents[size]=0; // Add terminating zero.
//Print it again for debugging
printf("Read %s\n", contents);
//Close the file
fclose(stream);
free(contents);
The function fread will read from the stream and not terminate on end-of-line characters.
From the man page, you have:
size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
which reads in nitems of size size.
fread reads all the files as-is:
if (fread(contents, 1, fileSize, stream) != fileSize) {
/* error occurred */
}
I've got this:
ssize_t filetomem(const char *filename, uint8_t **result)
{
ssize_t size = 0;
FILE *f = fopen(filename, "r");
if (f == NULL)
{
*result = NULL;
return -1;
}
fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, 0, SEEK_SET);
*result = malloc(size);
if (size != fread(*result, sizeof(**result), size, f))
{
free(*result);
return -2;
}
fclose(f);
return size;
}
Meaning of return value:
Positive or 0: successfully read the file
minus one: couldn't open file (possibly no such file)
minus two: fread() failed
I have a file that I need to read into a buffer (char *) but the problem is that the file has some "funny characters" in it inbetween the valid text.
So when I write some code like the following:
FILE *fp;
if((fp = fopen(".\\test.txt", "rt"))==NULL){
printf("Cannot open file2\n");
}
fseek(fp, 0, SEEK_END);
long int fsize = ftell(fp);
rewind(fp);
//char *buffer2 = malloc(fsize * sizeof(char));
buffer = malloc(fsize * sizeof(char));
fread(buffer, 1, fsize, fp);
buffer[fsize] = '\0';
fclose(fp);
printf("fsize = %i\n", fsize);
printf("Buffer = %s\n", buffer);
It only prints out the first part of the text file like follows:
Buffer = header
And obviously stops at the first NUL char.
Is thier any way to read the entire buffer of the file, including funny chars?
Or is this not possible in C?
The FSIZE is read correctly, just the FREAD does not read the entire buffer ;-(
Any help would be greatly appreciated ;-)
Thanks
Lynton
UPDATE: OK, I was being a little stupid.....if I write the buffer to a file it has everything in it, only if I write it out to the screen does it stop at the null so that is fine.
Don't open the file in "text" mode ("rt"), use binary mode instead ("rb").
Also, it might well be reading the data, but the printf("Buffer = %s\n", buffer) will only print up to the first NUL, so your debug is not going to do what your want. You probably want to write a little hex dumping function.
How to read all contents of file, including NUL chars between valid text?
Errors:
Allocate enough space if attempting to make a string. OP's code is 1 short. This is a dubious goal if data read may include null chracters.
Open in binary mode #Lawrence Dol
Some more error checking is useful.
// FILE *fp = fopen(".\\test.txt", "rt");
FILE *fp = fopen(".\\test.txt", "rb");
if (fp==NULL) {
printf("Cannot open file2\n");
exit(-1);
}
if (fseek(fp, 0, SEEK_END)) {
printf("fseek() trouble\n");
exit(-1);
}
long fsize = ftell(fp);
if (fsize == -1 || fsize >= SIZE_MAX) {
printf("fell() trouble\n");
exit(-1);
}
// Add 1 if trying to make a string.
size_t sz = (size_t) fsize;
if (making_a_string) sz++;
rewind(fp);
char *buffer = malloc(sizeof *buffer * sz);
if (buffer == NULL && sz > 0) { // Tolerate a file size of 0
printf("malloc() trouble\n");
exit(-1);
}
size_t in = fread(buffer, 1, fsize, fp);
fclose(fp);
if (in != fsize) {
printf("fread() trouble\n");
exit(-1);
}
if (making_a_string) {
buffer[fsize] = '\0';
}
To print the entire data, use, fwrite(). In order to print a character array, a trailing null chracter is not needed as in a string, but the length of the character array is used.
printf("fsize = %ld\n", fsize); // Note: %ld
printf("Buffer = <", );
fwrite(buffer, 1, fsize, stdout);
printf(">\n");