I'm having a difficult time trying to open a WAV file for reading. When I compile and run my code, I do not get any errors. I am adding the code that I am messing with (assuming necessary libraries have been called). The program is supposed to display the contents of the WAV file and although I enter a valid filename and extension, the statement "Invalid Filename. Try Again." is still being printed to the screen. The other method I attempted was enter the directory of the file instead of just the name, and when I do that, my program ends and nothing is displayed. Any guidance would be helpful and thank you in advance!
main(){
FILE *fin;
printf("\nEnter filename of WAV file: \n");
char filename[256];
scanf("%s",&filename);
fin = fopen(filename,"rb"); // opens in rb
if(!fin) // if file doesn't exist
{
printf("Invalid filename. Try again.\n");
}
else // if fin opens succesfully
{
printf("\nFile opened succesfully\n");
char *header;
header = (char *)malloc(44);
if(header == NULL)
{
printf("Error in allocating memory.");
return 0;
}
fread(header,1,44,fin);
char *chunkid;
unsigned int *chunksize;
char *format;
char *subchunk1id;
unsigned int *subchunk1size;
unsigned short int *audioformat;
unsigned short int *numchannels;
unsigned int *samplerate;
unsigned int *byterate;
unsigned short int *blockalign;
unsigned short int *bitspersample;
char *subchunk2id;
unsigned int *subchunk2size;
unsigned int *data;
chunkid = header;
chunksize = (unsigned int *)(header + 4);
format = header + 8;
subchunk1id = header + 12;
subchunk1size = (unsigned int *)(header + 16);
audioformat = (unsigned short int *)(header + 18);
numchannels = (unsigned short int*)(header + 20);
samplerate = (unsigned int*)(header + 24);
byterate = (unsigned int*)(header + 28);
blockalign = (unsigned short int*)(header + 30);
bitspersample = (unsigned short int*)(header + 32);
subchunk2id = header + 36;
subchunk2size = (unsigned int*)(header + 40);
data = (unsigned int*)(header + 44);
printf("\n%c%c%c%c",*(header),*(header+1),*(header+2),*(header+3));
printf("\n%d",*chunksize);
printf("\n%c%c%c%c",*(header + 8),*(header + 9), *(header + 10), *(header + 11));
printf("\n%c%c%c%c",*(header + 12),*(header + 13), *(header + 14), *(header + 15));
printf("\n%d",*subchunk1size);
printf("\n%d",*audioformat);
printf("\n%d",*numchannels);
printf("\n%d",*samplerate);
printf("\n%d",*byterate);
printf("\n%d",*blockalign);
printf("\n%d",*bitspersample);
printf("\n%c%c%c%c",*(header + 36),*(header + 37),*(header + 38), *(header + 39));
printf("\n%d",*subchunk2size);
printf("\n%d",*data);
fclose(fin);
} // end of else
} // end of main
Try using
if(!fin)
{
perror("Error:");
}
it will print the right error message for you to easily diagnose why your file couldn't be opened. May be your program cannot find the file specified by you or you might not have permissions to open it. Here's a list of errors you may encounter while opening a file.
The other possible problem that I could see is that you are using scanf to read from stdin into your char array. What if the path specified by you contains white-spaces? Every word followed by a White-space will be considered like a different string. And you'll get only the first longest possible word that doesn't contain white-space into it. So, your program isn't reading the entire path. You can try
scanf("%[^\n]", filename) which will read until a '\n' is encountered. Beware! This exposes you to buffer overflow possibilities, that if you pass a valid string set to the program which is of length greater than 256, you'll be writing beyond the boundaries of your char array and which isn't good. So try scanf("%255[^\n]", filename) or try using fgets() doc SO which provides buffer overflow protection.
Using warnings while compiling the code would have revealed your mistake.
Proposal for improvement, describe the header as a struct like:
typedef struct
{
char riff_tag[4];
int32_t riff_length;
char wave_tag[4];
char fmt_tag[4];
int32_t fmt_length;
int16_t audio_format;
int16_t num_channels;
int32_t sample_rate;
int32_t byte_rate;
int16_t block_align;
int16_t bits_per_sample;
char data_tag[4];
int32_t data_length;
}waveFileHeader, *waveFileHeaderptr ;
and read it like:
waveFileHeaderptr header =malloc ( sizeof (waveFileHeader));
fread (header , sizeof (waveFileHeader), 1 , fin);
will make the following code and handeling less messy
Related
So I have a binary file that I want to read that is structured such that there are 256 segments of the following structure:
First Byte: integer representing the length of the bits of the field following it that you need to read. It doesn't necessarily end at a byte boundary
Variable number of bits: The field you want to read. It doesn't necessarily end at a byte boundary
The file ends with 0's padded out so that it ends at a byte boundary.
I'm struggling to figure out an ideal method that involves reading as few individual bits as possible. I'm thinking of maybe reading the length first, dividing this value by 8 and reading that number of bytes next, and then using remainder of the previous operation (if any) to read the rest of the field bit by bit. I'm not sure if this is an ideal method however. Any suggestions?
Edit: Attached is a link to the files. The readable file is the format I would like to print out the binary file as.
To take an example from the desired output:
length for 9c: 4
code for 9c: 1101
4 would be the first byte read from the binary file, and 1101 would be the variable number of bits
https://ln2.sync.com/dl/e85dc8b40/3f5wbhaq-kxz3ijv8-wuts3t32-442gbsh2
The naive method works excellently (for small files)
The input is actually completely unaligned, just a series of bits, without any padding.
[I'll delete this answer in 1 minute, because I dont want do do someone's homework]
#include <stdio.h>
#include <stdlib.h>
#define the_path "/home/Download/binary_file.dict"
struct bitfile {
FILE *fp;
unsigned char byte;
unsigned char left;
};
struct bitfile * bfopen(char *path)
{
struct bitfile *bp;
bp = malloc(sizeof *bp);
bp->fp = fopen(path, "rb" );
bp->byte = 0;
bp->left = 0;
return bp;
}
int bfclose(struct bitfile * bp)
{
int rc;
rc = fclose(bp->fp);
free(bp);
return rc;
}
int bfgetb(struct bitfile * bp)
{
int ch;
if (!bp->left) {
ch = fgetc(bp->fp);
if (ch < 0) return EOF;
bp->byte = ch;
bp->left = 8;
}
bp->left -= 1;
ch = bp->byte & (1u << bp->left) ? 1 : 0;
// bp->byte >>= 1;
return ch;
}
void bfflush(struct bitfile * bp)
{
bp->left =0;
}
unsigned bp_get_n( struct bitfile *bp, unsigned bitcount)
{
unsigned val=0;
while(bitcount--) {
int ch;
ch = bfgetb(bp);
if (ch < 0) return EOF;
val <<=1;
val |= ch;
}
return val;
}
int main(void)
{
struct bitfile *bp;
int ch;
unsigned iseg, ibit, nbit;
bp = bfopen( the_path);
for (iseg =0; iseg <16*16; iseg++) {
// bfflush(bp);
nbit = bp_get_n(bp, 8);
fprintf(stdout, "Seg%u: %u bits\n", iseg, nbit);
fprintf(stdout, "payload:");
for (ibit=0; ibit < nbit; ibit++) {
ch = bfgetb(bp);
if (ch < 0) break;
fputc( '0'+ ch, stdout);
}
fprintf(stdout, ".\n");
}
bfclose(bp);
return 0;
}
In the program I have to make for an assignment we are given a .dat file, which has data in the format: ID number[9+1 character], last name[50+1], name[50+1], date of birth[3 integers], street[100+1 character], street number[integer], city[30+1 character].
From that .dat file I'm supposed to create a structure with all the data. My problem is that the ID number is read incorrectly, while the rest of it is read correctly. Plus, the ID number changes each time I compile the code.
I've tried reading the file from a separate function and from main, and I compared my code to the sample code our proffessor gave us, but I can't find an error. I also tried changing the ID type to integer, but the error persists.
The structure:
typedef struct {
char oib[9 + 1];
char prezime[50 + 1];
char ime[50 + 1];
int dan;
int mj;
int god;
char ulica[100 + 1];
int ulbroj;
char grad[30 + 1];
} Puk;
Function for reading from .dat file:
Puk* readPuk(int* n) {
FILE* fin = fopen("puk.dat", "rb");
fseek(fin, 0, SEEK_END);
int br = ftell(fin) / sizeof(Puk);
rewind(fin);
Puk* rez = (Puk*)malloc(sizeof(Puk) * br);
fread(&rez[0], sizeof(Puk), br, fin);
*n = br;
fclose(fin);
return rez;
}
The bit for outputting the data read:
Puk* pukBin = readPuk(&nPuk);
for (i = 0; i < nPuk; i++) {
fprintf(fout, "-----------\n");
fprintf(fout, "OIB: %d\nPrezime: %s\nIme:%s\nDatum:%d.%d.%d\nUlica:%s\nBroj:%d\nGrad:%s\n", pukBin[i].oib, pukBin[i].prezime, pukBin[i].ime, pukBin[i].dan, pukBin[i].mj, pukBin[i].god, pukBin[i].ulica, pukBin[i].ulbroj, pukBin[i].grad);
}
The issue was using a %d when outputting to a .txt file, instead of using a %s.
The following code is part of my program that tries to extract image features from a bitmap file. I need to extract information (width and height only) about the image and also make copies of it. These images are of 2048X 2168 resolution, 8-bit greyscale.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAMELENGTH 301
long getImageInfo(FILE* Finput, long offset, int nchars){
unsigned char *ptrChar;
unsigned char dummy;
long value=0L;
int i;
dummy='0';
ptrChar=&dummy;
fseek(Finput,offset,SEEK_SET);
for (i=1; i<=nchars; i++){
fread(ptrChar,sizeof(char),1,Finput);
value += ((long) ((*ptrChar)*pow(256,(i-1))));
}
return(value);
}
void copyImageInfo(FILE* Finput, FILE* Foutput){
unsigned char *ptrChar;
unsigned char dummy;
long offset;
int i;
dummy='0';
ptrChar=&dummy;
int byte_size = ((int) getImageInfo(Finput,34,4));
/* copying header: signature, image width & height, number bit/pixel, image size, number of colors */
offset=0L;
fseek(Finput,offset,SEEK_SET);
fseek(Foutput,offset,SEEK_SET);
for (i=0; i<=54; i++){
fread(ptrChar,sizeof(char),1,Finput);
fwrite(ptrChar,sizeof(char),1,Foutput);
}
/* copying pixel data */
/* This part of the code may not be complete */
offset=54L;
fseek(Finput,offset,SEEK_SET);
fseek(Foutput,offset,SEEK_SET);
for (i=0; i<=byte_size; i++){
fread(ptrChar,sizeof(char),1,Finput);
fwrite(ptrChar,sizeof(char),1,Foutput);
}
}
int main(int argc, char *argv[]){
FILE* Finput;
FILE* Foutput;
char input_name[NAMELENGTH];
char output_name[NAMELENGTH];
char job_name[NAMELENGTH];
char history_name[NAMELENGTH];
unsigned char *ptrChar;
int pix_width,pix_height;
int bit_pixel,byte_size,ncolors;
strcpy(input_name,argv[1]); /* first argument contains path to the image file */
strcpy(job_name, argv[1]);
job_name[strlen(job_name)-4]='\0';
sprintf(history_name,"%s%s",job_name,"_hist.txt"); /* history file stores image header information */
if( (Finput=fopen(input_name,"r"))==NULL ){
fprintf(stderr,"\n ERROR: file %s could not be opened for reading\n",input_name);
exit(-1);
}
else{
fseek(Finput,0L,SEEK_END);
if (getImageInfo(Finput,0,2)!=19778) fprintf(stdout,"\n WARNING: wrong BMP signature!\n");
pix_width = ((int) getImageInfo(Finput,18,4));
pix_height = ((int) getImageInfo(Finput,22,4));
bit_pixel = ((int) getImageInfo(Finput,28,2));
byte_size = ((int) getImageInfo(Finput,34,4));
ncolors = ((int) getImageInfo(Finput,46,4));
fprintf(stdout,"\n width pixels=%d",pix_width);
fprintf(stdout,"\n height pixels=%d",pix_height);
fprintf(stdout,"\n bits per pixel=%d",bit_pixel);
fprintf(stdout,"\n image data size=%d",byte_size);
fprintf(stdout,"\n number colors=%d\n",ncolors);
/* history file */
if ( (Foutput=fopen(history_name,"a"))==NULL ){
fprintf(stderr,"\n ERROR: file %s could not be opened for appending\n",history_name);
exit(-1);
}
else{
fprintf(Foutput,"Path to Image: %s ",input_name);
fprintf(Foutput,"\n\t 18 - biWidth - width pixels=%d",pix_width);
fprintf(Foutput,"\n\t 22 - biHeight - height pixels=%d",pix_height);
fprintf(Foutput,"\n\t 28 - biBitCount - bits per pixel=%d",bit_pixel);
fprintf(Foutput,"\n\t 34 - biSizeImage - image data size=%d",byte_size);
fprintf(Foutput,"\n\t 46 - biClrUsed - number colors=%d\n",ncolors);
fclose(Foutput);
}
sprintf(output_name,"%s%s",job_name,"_copy.bmp");
if ( (Foutput=fopen(output_name,"wb"))==NULL ){
fprintf(stderr,"\n ERROR: file %s could not be opened for writing\n",output_name);
exit(-1);
}
else{
copyImageInfo(Finput,Foutput);
fclose(Foutput);
}
}
fclose(Finput);
}
Unfortunately, my original image files are in tif format. So when I convert them, I am unable to preserve some of the header file information. One online tool lets me preserve the bits-per-pixel (8 bit) but then I lose the biSizeImage (which turns to 0). Another conversion tool gets me the size correctly but image bitrate changes to 24. (link1, link2)
An example of my original tif image (temporary_link1) and the corresponding BMP image (temporary_link2)
When I run the above, I am able to copy the header information correctly but not the pixel data. If this can be copied using some other method (like for example by comparing the EOF), it may be a good alternative. I am unsure about calculating the padding and also the direction of writing.
Any guidance would be appreciated starting with the correct conversion of tif format to my required bmp format. Evidently I am new to image formatting and compression.
Output:
width pixels=2048
height pixels=2168
bits per pixel=8
image data size=0
number colors=0
getImageInfo is incorrect. The integer values are supposed to be saved in little-endian format. It should be read as follows:
unsigned int getImageInfo(FILE *fin, long offset, int nchars)
{
fseek(fin, offset, SEEK_SET);
unsigned int value = 0;
for(int i = 0; i < nchars; i++)
{
unsigned char dummy = '0';
fread((char*)&dummy, sizeof(char), 1, fin);
value += dummy << (8 * i);
}
return value;
}
byte_size is not guaranteed to be set to the correct value. This should be roughly equal to width * height * bit_pixel. Use this formula.
byte_size = ((pix_width * bit_pixel + 31) / 32) * 4 * pix_height;
Moreover, 8-bit image includes color table of size 1024. This table is immediately after 54 byte header, and before the pixel data. Read it as follows:
unsigned int getImageInfo(FILE *fin, long offset, int nchars)
{
fseek(fin, offset, SEEK_SET);
unsigned int value = 0;
for(int i = 0; i < nchars; i++)
{
unsigned char dummy = '0';
fread((char*)&dummy, sizeof(char), 1, fin);
value += dummy << (8 * i);
}
return value;
}
void copyImageInfo(FILE* Finput, FILE* Foutput)
{
int w = getImageInfo(Finput, 18, 4);
int h = getImageInfo(Finput, 22, 4);
int bit_pixel = getImageInfo(Finput, 28, 2);
int byte_size = ((w * bit_pixel + 31) / 32) * 4 * h;
int ncolors = getImageInfo(Finput, 46, 4);
fprintf(stdout, "\n width pixels=%d", w);
fprintf(stdout, "\n height pixels=%d", h);
fprintf(stdout, "\n bits per pixel=%d", bit_pixel);
fprintf(stdout, "\n image data size=%d", byte_size);
fprintf(stdout, "\n number colors=%d\n", ncolors);
char header[54]; //bitmap header
char *pixels = malloc(byte_size); //pixel data
fseek(Finput, 0, SEEK_SET);
fseek(Foutput, 0, SEEK_SET);
fread(header, sizeof(header), 1, Finput);
fwrite(header, sizeof(header), 1, Foutput);
if(bit_pixel <= 8)
{
//color table
int colors_size = 4 * (1 << bit_pixel);
char *colors = malloc(colors_size);
fread(colors, 1, colors_size, Finput);
fwrite(colors, 1, colors_size, Foutput);
free(colors);
}
fread(pixels, 1, byte_size, Finput);
fwrite(pixels, 1, byte_size, Foutput);
free(pixels);
}
int main(void)
{
char input_name[] = "input.bmp";
char output_name[] = "output.bmp";
FILE *Finput = fopen(input_name, "rb");
if(!Finput)
{
fprintf(stderr, "\n ERROR: file %s\n", input_name);
exit(-1);
}
FILE *Foutput = fopen(output_name, "wb");
if(!Foutput)
{
fprintf(stderr, "\n ERROR: file %s\n", input_name);
fclose(Finput);
exit(-1);
}
if(getImageInfo(Finput, 0, 2) != 19778)
fprintf(stdout, "\n WARNING: wrong BMP signature!\n");
else
copyImageInfo(Finput, Foutput);
fclose(Foutput);
fclose(Finput);
return 0;
}
I have a network capture tool that captures packets and does some processing on them. Now, here is a small fragment of the code. u_char is the name given to unsigned char. When I try to print the variable smac to stdout, all I get is 000000000000 on the screen. I want to print the actual smac and dmac.
char * str;
char converted[6*2 + 1];
u_char smac[6], dmac[6];
int i;
if (ntop_lua_check(vm, __FUNCTION__, id, LUA_TSTRING))
return(CONST_LUA_PARAM_ERROR);
if ((str = (char*)lua_tostring(vm, id)) == NULL)
return(CONST_LUA_PARAM_ERROR);
sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&smac[0], &smac[1], &smac[2], &smac[3], &smac[4], &smac[5]);
for (i = 0; i < 6; i++)
{
sprintf(&converted[i*2], "%02X", smac[i]);
}
printf("%s\n", converted);
Is the problem with unsigned char getting promoted to int or something by sprintf and printing the unnecessary two bytes? I am not sure.Any help would be of great value. Thank you.
Firstly, i'm not very familiarized with C, i come from Java, C#, C++... and possibly i inherited defects from this languages in order to realize this practice, well i have the follows question, here is my code:
#include <stdio.h>
#include <stdlib.h>
void decrypt(unsigned long* v, unsigned long* k);
const int MAX = 32;
const long delta = 0x9e3779b9;
long sum=0xC6EF3720;
int main() {
FILE *fp;
FILE *destino;
unsigned long v[2];
unsigned long k[4] = { 128, 129, 130, 131 };
unsigned long tam=0;
char* buffer;
char* aux[sizeof(unsigned long)];
int i;
if ((fp = fopen("image.png", "rb")) == NULL) {
printf ("Error! \n ");
return 0;
}
else {
fread(&aux,sizeof(unsigned long),1,fp);
memcpy(&tam,&aux,sizeof(unsigned long));
buffer = (char*)malloc(tam);
//fread(&buffer,1,tam,fp);
char *buffer2[28568];
fread(&buffer2,1,28568,fp);
/*for(i = 0;i < tam;++i) {
printf("%c", ((char *)buffer2)[i]);
}*/
for(i=4;i<tam;i+=8) {
memcpy(&v,&buffer2[i],8);
decrypt(&v,&k);
}
if ((result= fopen("image2.png", "rb")) == NULL) {
printf ("Error! \n ");
return 0;
}
else {
fwrite(v,sizeof(unsigned long)*2,1,result);
fclose (result);
fclose(fp);
}
}
return 0;
}
void decrypt(unsigned long* v, unsigned long* k) {
int i=0;
while(i<MAX) {
v[1] = v[1] -((4 << v[0])+(k[2]^v[0])+(sum^(5 >> v[0]))+k[3]);
v[0] = v[0] -((4 << v[1])+(k[0]^v[1])+(sum^(5 >> v[1]))+k[1]);
sum = sum-delta;
i++;
}
}
Where tam is the size of my binary file (image in this case) where i store first 4 bytes (unsigned long) where is located the size in my png file (28568)
When i create my char* buffer i have to assign dynamically with malloc but when i make a new fread from my file i get a "No source available for "msvrct!memcpy() at 0xrandom_memory_address" from Eclipse when i debug, well, i comment this line and i try to make it manually set a new buffer2 with 28568 as size of my array, apparently works, making a iteration of buffer2 prints ascii characters values but when i call decrypt for make the decryption of my image, the final result is stored in v array which i have to copy in a new file, i tried to search how to make a empty image png in C but i didn't find anything, so i created a copy of my encrypt image calling it "image2.png" but i suppose this not the "clean solution" for that, because for the other hand is not working at all.
For more explanation about this exercise just say that the decrypt funcion work with blocks of 8 bytes (64 bits) that through a key (array k) make a series of operation where they store in v array itself, crossing through the loop 8 in 8 and retrieve the value of buffer in v in each one, after the loop execution we have the result in v and only left to copy in a new file where finally show up the image decrypt.
It's a very complex practice for all of one newbies in C, it's driving my crazy trying to figure out what i doing wrong.
I hope anyone can see what i'm not able to for now.
I think you are having problems with the declarations of the buffers. I think the correct should be:
FILE *fp;
FILE *destino;
unsigned long v[2];
unsigned long k[4] = { 128, 129, 130, 131 };
unsigned long tam=0;
char* buffer;
char aux[sizeof(unsigned long)]; // without the "*"
int i;
if ((fp = fopen("image.png", "rb")) == NULL) {
printf ("Error! \n ");
return 0;
}
else {
fread(aux,sizeof(unsigned long),1,fp);
memcpy(&tam,aux,sizeof(unsigned long));
buffer = (char*)malloc(tam);
//fread(buffer,1,tam,fp); // without the "&" in this case
char buffer2[28568]; // without the "*"
fread(buffer2,1,28568,fp); // or fread(buffer,1,tam,fp);
/*for(i = 0;i < tam;++i) {
printf("%c", buffer2[i]); // or buufer[i] if you change to use it again
}*/
for(i=4;i<tam;i+=8) {
memcpy(v,&buffer2[i],8);
decrypt(v,k);
}
...
I don't fully understand what you are trying to accomplish, but one problem is here:
char* aux[sizeof(unsigned long)];
// ... some code ...
fread(&aux,sizeof(unsigned long),1,fp);
Understand that char* aux[sizeof(unsigned long)]; means that you are declaring a double pointer, but fread() prototype states that the destination is a single pointer:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
so what you should be doing instead is:
char aux[sizeof(unsigned long)];
// ... some code ...
fread(aux,sizeof(unsigned long),1,fp);
Don't complicate things that are not complicated!
You also do this mistake in other parts of your code, you need to re-check everything, ok? Again:
char *buffer2[28568];
fread(&buffer2,1,28568,fp);
should be:
char buffer2[28568];
fread(buffer2, 1, 28568, fp);
// or: fread(buffer2, 1, sizeof(buffer2), fp);
There are some interesting tutorials on pointers and arrays, I suggest you read some.