Convert a file into binary buffer in C? - c

I'm just starting in c/c++. I'm able to write a file from binary :
FILE *myFile= fopen("/mnt/music.mp3", "ab+"); // Doesn't exist
fwrite(binaryBuffer, sizeOfBuffer, 1, myFile);
All I want is to get a new "binaryBuffer" from "myFile"
How I can do that ?
Thanks !

Use the fread function, which works just like fwrite:
char buffer[BUFFER_SIZE]; // declare a buffer
fread(buffer, length, 1, file); //read length amount of bytes into buffer
If you don't know how many bytes to read you can seek to the end of the file to find the length.
(If you read from the same file you just wrote to you will want to rewind)
http://www.cplusplus.com/reference/cstdio/fread/

Related

C - Writing a buffer as binary file (wav)

I am reading a wav file as binary, putting it in a buffer and I want to write the exact same wav file again.
Here is my code so far:
file = fopen("tone1.wav", "rb");
file3 = fopen("outout.wav","wb");
fseek(file, 0, SEEK_END);
fileLen=ftell(file);
fseek(file, 0, SEEK_SET);
buffer=(char *)malloc(fileLen+1);
buffer3=(char *)malloc(fileLen+1);
fread(buffer, fileLen, 1, file);
for (int i=0;i<fileLen+1;++i){
buffer3[i]=buffer[i];
fwrite(buffer3,sizeof(buffer3),1,file3);
}
fclose(file);
fclose(file3);
free(buffer);
free(buffer3);
The problem is that the outout wav file comes empty and unplayable.
I am not sure what i'm doing wrong. If I replace fwrite(buffer3,sizeof(buffer3),1,file3); by fwrite(buffer3,sizeof(buffer3),1048,file3); (let's say 1048) I get something playable but not the entire wav with a loop in it.
Can anyone tell me what's the problem? Maybe it's the for loop length that's wrong maybe i shouldn't put fileLen as a limit to it? What should i replace 1 by?
Thanks in advance
Please observe the following:
the fact that the file is "raw" and has a ".wav" extension, as you put it, does neither mean it is a wav file nor makes a wav file out of it. In order to become a wav file it needs a valid WAV header and requires proper audio file API for reading and writing. What you're reading and copying is headerless data of unknown format and unknown endianness.
if you want use to standard library C functions for copying contents from one file to another, you do it on the byte level, without interpreting the content, which is what you do.
In that case, there are few issues in your code:
redundant padding of the buffers and casting the return of malloc in C:
buffer = malloc(fileLen); should work.
ambiguous logic: why do you, upon having read the source file in one pass, both copy buffers and write to the destination file byte-per-byte, inside the loop?
even if so, you are still passing incorrect arguments to fread and fwrite functions, please, check man pages. fread(buffer, 1, fileLen, file); should fix the read. (1 equals sizeof (char)).
why do you need a redundant buffer buffer3 if you don't interpret the content of file?
even if so, you are still passing incorrect arguments to your functions inside the loop. This should do the fix:
for (int i=0; i<fileLen; i++){
buffer3[i]=buffer[i];
fwrite(&(buffer3[i]),1,1,file3);
}
Generally one doesn't know the size of the file in advance, before opening the source file. So one allocates the buffer of reasonable size, then reads and writes in chunks determined by the size of the buffer. In that case your read routine should also handle the buffer underflow condition.
Do not write inside the loop.
Or write diferent characters every time (not always buffer3[0]).
fread(buffer, fileLen, 1, file);
for (int i = 0; i < fileLen; ++i) {
// transform and copy
buffer3[i] = transform(buffer[i]);
//fwrite(buffer3 + i, 1, 1, file3); // write 1 character only
}
fwrite(buffer3, fileLen, 1, file3); // write all the new buffer
I solved it by putting fwrite(buffer3,sizeof(char),78000,file3); outside of the for loop, with 78000 being the size of the file1. But my question is, how can i know what is its size by code?

About the FILE * streams and how fputc() works

I wonder about the operation of FILE pointer f and how the function fputc works.
First, when I open a file (I have not been working on it yet, like writing or reading). What position of f in the file? Is it before the first character?
Second, when I use:
fseek(f, -1, SEEK_CUR);
fputc(' ', f);
what position of my pointer f now?
Reading the manuals should help you.
For fopen: the stream is positioned at the beginning of the file. Except for mode like 'a'
For fseek: that function can fail, you have to test the return value; and it is not difficult to imagine that you cannot obtain a negative offset.
When you open the file, the current position is 0, at the first character.
If you try to fseek before the beginning of the file, fseek will fail and return -1.
Note that if you seek backwards on a text file, there is no guarantee that is can succeed. On linux and/or for a binary stream, assuming you are not at the start of the stream, opened in write mode for a real file, after the sequence
fseek(f, -1L, SEEK_CUR);
fputc(' ', f);
the position of the stream will be the same as before the fseek.
But consider this seemingly simpler example:
fputc('\n', f);
fseek(f, -1L, SEEK_CUR);
On systems such as Windows, where '\n' will at some point be converted into a sequence of 2 bytes <CR><LF>, what do you think it should do?
Because of all these possibilities for failure (and a few more exotic ones), you should always test the return value of fseek and try to minimize its use.
When accessing files through C, the first necessity is to have a way to access the files. For C File I/O you need to use a FILE pointer, which will let the program keep track of the file being accessed. For Example:
FILE *fp;
To open a file you need to use the fopen function, which returns a FILE pointer. Once you've opened a file, you can use the FILE pointer to let the compiler perform input and output functions on the file.
FILE *fopen(const char *filename, const char *mode);
Here filename is string literal which you will use to name your file and mode can have one of the following values
w - open for writing (file need not exist)
a - open for appending (file need not exist)
r+ - open for reading and writing, start at beginning
w+ - open for reading and writing (overwrite file)
a+ - open for reading and writing (append if file exists)
Following is the declaration for fseek() function.
int fseek(FILE *stream, long int offset, int whence)
SEEK_SET Beginning of file
SEEK_CUR Current position of the file pointer
SEEK_END End of file
Following fputc() example :
/* fputc example: alphabet writer */
#include <stdio.h>
int main ()
{
FILE * pFile;
char c;
pFile = fopen ("alphabet.txt","w");
if (pFile!=NULL) {
for (c = 'A' ; c <= 'Z' ; c++)
fputc ( c , pFile );
fclose (pFile);
}
return 0;
}
It depends on your current position/offset for an example if your file pointer was on 100th offset and you write fseek(f, -1, SEEK_CUR); and the offset will be at 99th position, and then you write space on 99th position, after writing space using fputc(' ', f); file pointer's offset will be 100th again.

fread, fwrite for big size video file (about 180MB)

I want to read a video file and save as binary and write as a video file again.
I tested with 180MB video. I used fread function and It occur segmentation fault because array size is small for video.
those are my questions:
I use 160*1024 bytes char array. What is the maximum size of char array? How I can solve this problem?
this program need to work as:
read 128 bytes of video -> Encrypt -> write 128 byte
read next 128 bytes -> Encrypt -> write to the next.
I can't upload my code because of security rule of company. Any tip would be appreciated.
first use fseek() with SEEK_END, then use ftell() to determine the file size, after that allocate the needed memory with malloc() and write the data to that memory.
If I understand you correctly you don't need to allocate so much memory, but only 128 Bytes.
char buf[128];
while(/* condition */)
{
ret = fread(buf, sizeof buf, 1, fp_in);
encrypt(buf);
ret = fwrite(buf, sizeof buf, 1, fp_out);
}

replace bytes in file c

I got some code and I want improve it to find and replace bytes in file
so
I want to find all origbytes in FILE and then replace it with newbytes
then save file, I know how to open, write and save, but hot I can find bytes in char?
FILE* file;
file = fopen("/Users/Awesome/Desktop/test", "r+b");
int size = sizeof(file)+1;
char bytes [size];
fgets(bytes, size, file);
for (int i=0; i<size; i++){
char origbytes [] = {0x00, 0x00};
char newbytes [] = {0x11, 0x11};
if (strcmp(bytes[i], origbytes)) //Here the problem
{
fseek(file, i, SEEK_SET);
fwrite(newbytes, sizeof(newbytes), 1, file);
}
}
fclose(file);
strcmp() is for string compare and not character compare. Two characters can be compared directly
if ( bytes[i] == origbytes[something] )
Also you you should not apply sizeof() on a file pointer to determine file size. You should seek to the end of file using fseek and then query ftell except for binary files. For binary files, use something like fstat
One more thing to note is that fgets returns much before the EOF if it sees a newline. Hence in your code, you may not read entire file contents even after doing the changes that we suggested. You need to use fread appropriately
Strings are null terminated in the C standard library. Your search data is effectively a zero length string. You want memcmp instead.
memcmp (&bytes [i], origBytes, 2)
Firstly sizeof(file) + 1 just returns you the size of a pointer + 1. I don't think you need this for the size of the file. Use this: How do you determine the size of a file in C?
Then since you compare bytes (more or less smae as char) you simply compare using =
you can use fseek and then ftell functions to get the file size, not sizeof.

c programming read() and write() content to file

The user should input some file names in the command line and the program will read each file name from argv[] array. I have to perform error checking etc.
I want to read each filename. For example, if argv[2] is 'myfile.txt', the program should read the content of 'myfile.txt' and store value in char buffer[BUFSIZ] and then write the content of buffer into another file.
However before the content is written, the program should also write the name of the file and the size. Such that the file can be easily extracted later. A bit like the tar function.
The file I write the content of buffer, depending on the number of files added by user, should be a string like:
myfile.txt256Thisisfilecontentmyfile2.txt156Thisisfile2content..............
My question is
1) How do I write value of argv[2] into file using write() statement, as having problems writing char array, what should I put as (sizeof(?)) inside write(). see below as I don't know the length of the file name entered by the user.
2) Do I use the '&' to write an integer value into file after name, for example write 4 bytes after file name for the size of file
Here is the code I have written,
char buffer[BUFSIZ];
int numfiles=5; //say this is no of files user entered at command
open(file.....
lseek(fdout, 0, SEEK_SET); //start begging of file and move along each file some for loop
for(i=0-; ......
//for each file write filename,filesize,data....filename,filesize,data......
int bytesread=read(argv[i],buffer,sizeof(buffer));
write(outputfile, argv[i], sizeof(argv)); //write filename size of enough to store value of filename
write(outputfile, &bytesread, sizeof(bytesread));
write(outputfile, buffer, sizeof(buffer));
But the code is not working as I expected.
Any suggestions?
Since argv consists of null-terminated arrays, the length you can write is strlen(argv[2])+1 to write both the argument and null terminator:
size_t sz = strlen (argv[2]);
write (fd, argv[2], sz + 1);
Alternatively, if you want the length followed by the characters, you can write the size_t itself returned from strlen followed by that many characters.
size_t sz = strlen (argv[2]);
write (fd, &sz, sizeof (size_t));
write (fd, argv[2], sz);
You probably also need to write the length of the file as well so that you can locate the next file when reading it back.
1., You can write the string the following way:
size_t size = strlen(string);
write(fd, string, size);
However, most of the time it's not this simple: you will need the size of the string so you'll know how much you need to read. So you should write the string size too.
2., An integer can be written the following way:
write(fd, &integer, sizeof(integer));
This is simple, but if you plan to use the file on different architectures, you'll need to deal with endianness too.
It sounds like your best bet is to use a binary format. In your example, is the file called myfile.txt with a content length of 256, or myfile.txt2 with a content length of 56, or myfile.txt25 with a content length of 6? There's no way to distinguish between the end of the filename and the start of the content length field. Similarly there is no way to distinguish between the end of the content length and the start of the content. If you must use a text format, fixed width fields will help with this. I.e. 32 characters of filename followed by 6 digits of content length. But binary format is more efficient.
You get the filename length using strlen(), don't use sizeof(argv) as you will get completely the wrong result. sizeof(argv[i]) will also give the wrong result.
So write 4 bytes of filename length followed by the filename then 4 bytes of content length followed by the content.
If you want the format to be portable you need to be aware of byte order issues.
Lastly, if the file won't all fit in your buffer then you are stuffed. You need to get the size of the file you are reading to write it to your output file first, and then make sure you read that number of bytes from the first file into the second file. There are various techniques to do this.
thanks for replies guys,
I decided not to use (size_t) structure instead just assigned (int) and (char) types so I know exact value of bytes to read() out. ie I know start at beggining of file and read 4 bytes(int) to get value of lenght of filename, which I use as size in next read()
So, when I am writing (copying file exactly with same name) users inputted file to the output file (copied file) I writing it in long string, without spaces obviously just to make it readable here,
filenamesize filename filecontentsize filecontent
ie 10 myfile.txt 5 hello
So when come to reading that data out I start at begining of file using lseek() and I know the first 4 bytes are (int) which is lenght of filename so I put that into value int namelen using the read function.
My problem is I want to use that value read for the filenamesize(first 4 bytes) to declare my array to store filename with the right lenght. How do I put this array into read() so the read stores value inside that char array specified, see below please
int namelen; //value read from first 4 bytes of file lenght of filename to go in nxt read()
char filename[namelen];
read(fd, filename[namelen], namelen);//filename should have 'myfile.txt' if user entered that filename
So my question is once I read that first 4 bytes from file giving me lenght of filename stored in namelen, I then want to read namelen amount of bytes to give me the filename of originally file so I can create copied file inside directory?
Thanks

Resources