File operation to copy one .mp3 file to create another same file - c

I was trying to copy the contents of one music file(.mp3) to create another music(.mp3) file. I tried this,
#include<stdio.h>
#include<conio.h>
int main()
{
FILE *a, *b;
char c;
a = fopen("linkinpark.mp3","rb");
b = fopen("linkinpark1.mp3","wb");
while((ch = getc(a)) != EOF)
fprintf(b,"%c",ch);
fclose(a);
fclose(b);
return 0;
}
May be i am making some mistake like using a char variable and writing it in a binary file and also linkinpark1.mp3 is created but its corrupted.
What could be its possible solution?

getc() returns either an int, not a char. It needs to return int because it returns either the next byte read from the stream as a value between 0 and 255, or the value EOF, which is typically -1. Since there are 257 possible outputs, you need to be able to distinguish between the byte 255 and the sentinel EOF, but your code is conflating the two. Hence, once you hit the first byte with value 255, it erroneously cuts the file off short.
If you change c to be int instead of char, it should work correctly.

Related

Getting garbage value in structure when reading from file

I have a text file like this
987jgkfl
12358ldjkdju
7579jngj
8uuujkl
09698fjfj
I have a structure like this
struct emprec
{
int empid;
int todo;
char name[20];
};
I write the values of the struct into file like this
fd = fopen("/home/tarun/Desktop/test34.txt","a+");
fprintf(fd,"%d",temp2.empid);
fprintf(fd,"%s",temp2.name);
count++;
fclose(fd);
But when i read from the file i am getting the garbage value
while(i<=count)
{
fread(&temp5,sizeof(temp5),1,fd);
//fscanf(fd,"%d,%s",&temp5.empid,temp5.name);
//int k = strlen(temp5.name);
//printf("Value of k is %d\n",k);
//temp5.name[7]= '\0';
//fread(&temp5.empid,sizeof(temp5.empid),1,fd);
//fread(temp5.name,20,1,fd);
printf("\n%d %s",temp5.empid,temp5.name);
i++;
}
fclose(fd);
Please tell me where am i going wrong
Like say nemetroid :
You're writing a textual representation (with
fptrinf) of your struct but attempting to read a binary representation
(with fread).
For example, suppose you want write an int in a file. By doing like this :
fd = fopen("file","a+");
fprintf(fd,"%d",42);
You will write the character '4' and the character '2'. In ASCII, '4' is 0x34 and '2' is 0x32.
If you want to read that file and try to put it in an 4 bytes integer by doing like this :
int a = 0;
fread(&a,sizeof(a),1,fd);
The variable 'a' will contain the data on the file :
a = 0x00003234
And not 42 (0x0000002a) as you expect.
There were some calls that was missing from your code:
fflush()
Used to flush the file's buffer, you have to call this if you performed writes to the file and now you want to read
fseek
Used to set the file position indicator. In your case, the file position indicator was at the end of the file. Use fseek() to set the file position to where you started writing and than start reading.
fscanf function corresponds to fprintf. fread corresponds to fwrite. It means if you want to dump the structure using fprintf, then read it using fscanf. if you want to read the structure using fread then dump it using fwrite. Referring manpages of these functions should help.

Having problems Reading a file in C

I am trying to solve a problem which requires me to read a file and generate another file which has the same contents as the original but every fourth byte removed.I tried it doing this way ...
int main()
{
FILE *p;
FILE *q;
int i=0,k=0;
char c;
p = fopen("C:\\Users\\Teja\\Desktop\\Beethoven.raw","rw");
q = fopen("C:\\Users\\Teja\\Desktop\\Beethoven_new.raw","w+");
printf("%x is the EOF character \n",EOF);
while((c=fgetc(p))!=EOF)
{
if(i==3){
i=0;
printf("Removing %x %d \n",c,k++);
}
else{
printf("Putting %x %d \n",c,k++);
fputc(c,q);
i++;
}
}
fclose(p);
fclose(q);
return 0;
}
The file that i was trying to read is a .raw file and it is around 10-15 MB. I notice that the above code stops reading the file after typically 88 bytes. Is there any way to read large files or am i doing anything wrong ?
In addition to what has already been pointed out, a note on opening files: It sounds like your file in a binary file, which means you must add a b to the mode string. Additionally, rw is not a mode, since you only read from p you want rb, and since you only write to q you want wb or wb+.
By the way, the reason why you need fgetc to return an int is because fgetc must return 257 unique values: all the possible values of char, that is 0x00 thru 0xFF as well as something unique to signify EOF, usually -1
Change
char c;
to
int c;
as the return type of fetgetc() is an int and not char.

Unknown Logical Error Using the getc() Function in C

I'm attempting to use the getc() function to copy the contents of one file into another. But I'm making an unknown logical error because the output of the following program is a bunch of garbage.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *f;
FILE *write;
f = fopen("nums.csv","r");
write = fopen("numsWrite.dat","w");
char tempChar;
int i;
for(i = 0; (tempChar = getc(f)) != EOF; i++)
{
tempChar = getc(f);
fprintf(write,"%c",tempChar);
}
fprintf(write,"\n");
fclose(f);
fclose(write);
return 0;
}
content of nums.csv is:
1256,2548,35151,15,56,38
program returns:
2624,55,55,8
There are several problems with your code.
int main() should be int main(void); this is a minor issue that almost certainly won't hurt anything, but the latter is more correct.
You don't check whether the fopen() calls succeed.
You're using i to count the characters you read, but you never do anything with its value.
The getc() function returns a result of type int, so you should definitely make tempChar an int. The reason for this is that it can return either a valid character value (which will fit in a char object) or the value EOF which is typically -1. By storing the result of getc() in a char object, either you'll never see EOF (if plain char is unsigned), or you won't be able to distinguish EOF from a valid input character.
In a comment on Razvan's answer, you said you changed the test to tempChar != EOF. Apart from the problem I explained above, on the first iteration of the loop tempChar has not been initialized, and the result of the comparison is unpredictable.
The conventional way to write an input loop using getc() is:
int c;
while ((c = getc(f)) != EOF) {
/* do something with c */
}
As a matter of style, write is not a very good name for a FILE*. For one thing, there's a function of that name (defined by POSIX, not by C, but it's still potentially confusing). You might call the FILE* objects in and out instead.
You call getc two times: once in the for condition and once in the for body. Delete this line: tempChar = getc(f); and try again.

File handling in C: can't fathom the output

I compiled this (gcc compiler) :
#include< stdio.h>
main() {
unsigned char ch;
FILE *fp;
fp=fopen("trial","r");
while((ch=getc(fp))!=EOF)
printf("%c",ch);
fclose(fp);
}
It gives the follwing:
Warning: comparison is always true due to limited range of the data type
On executing, an endless stream of characters is printed on terminal.
(Assuming I created a file named "trial" before compiling the program and wrote some text in the file.)
Kindly explain the warning.....
Because EOF is -1 and your ch is unsigned char which means ch will never become -1.
Instead use int ch;
The EOF value in C is an int while ch here is a char. The char type is smaller than int and hence can represent less values than int can. EOF is one of the values which char simply can't ever represent and hence ch will never be equal to EOF.
In this scenario getc actually returns an int so it can represent EOF. But you are immediately shrinking it to a char and losing that extra information.
Here's a way to properly write this.
int cur;
FILE *fp;
fp=fopen("trial","r");
while((cur = getc(fp))!=EOF) {
unsigned char ch = cur;
printf("%c",ch);
}
fclose(fp);
getc() returns an int. You're truncating (and changing the signedness) it to unsigned char with that assignment, so it will never match EOF. Just change the type of ch to int and you'll be fine.
getc returns an integer for good reason. The EOF indicator is outside the range of a normal char, because otherwise you could confuse a legitimate character with the EOF indicator. However, you're assigning the results to a character which confines the answer to fall within the limits of a char value. In short, you're never going to know when the end of the file has been reached this way. Make "ch" an int type or assign result from call to getc to an unsigned char type after you compare it with EOF.

Find and Replace in a C File

The Problem was to find and replace a string in a C File.
I am new to C Files. I have tried the following code but I didnt get any output:
#include<stdio.h>
#include<string.h>
int main()
{
FILE *f1,*f2;
char *src,*dest,*s1,ch,ch1,ch2,ch3;
int i;
f1=fopen("input.txt","rw");
f2=fopen("dummy.txt","rw");
src="mor";
dest="even";
while(ch!=EOF)
{
ch=fgetc(f1);
if(ch==src[0]) //Finding 1st char of src
{
fgets(s1,strlen(src),f1);
if(strcmp(src+1,s1)==0) //Finding occurance of "src" in file
{
fseek(f1,strlen(src)-1,SEEK_CUR);
while(ch1!=EOF) //Copying remaining data into another file
{
ch1=fgetc(f1);
fputc(ch1,f2);
}
fseek(f1,-strlen(src),SEEK_CUR);
for(i=0;i<strlen(dest);i++) //replacing "src" with "dest"
{
ch2=dest[i];
fputc(ch2,f1);
}
fclose(f1);
f1=fopen("input.txt","a");
while(ch3!=EOF) //Appending previosly copied data into 1st file
{
ch3=fgetc(f2);
fputc(ch3,f1);
}
}
}
}
fclose(f1);
fclose(f2);
}
The Contents of input.txt is "morning".
Kindly point the ERROR in the logic and also give an efficient code for the same.
Thanks in Advance.
Reading files in C is usually a bit messy. The first problem that I see is the way ch is used in the main loop. The first time
while (ch != EOF)
is executed, ch is uninitialized, and if it happens to hold EOF, the main loop will not execute at all. I usually use the following structure for reading from files:
FILE *fInput = fopen("input.txt", "r");
int ch; /* need an int to hold EOF */
for (;;)
{
ch = fgetc(fInput);
if (ch == EOF) break;
...
}
In addition, you may need to read up on file pointer concept. For example, after reading the remainder of src, you fseek() forward, and skip some more characters before you copy data to f2. Essentially, you read m, read or (with fgets() - and into an unallocated buffer s1 that would go ka-boom on you some time in the near future), skip 2 more characters (now your pointer is at last n of "morning"), copy "ng" into f2, try to write EOF to f2 in this loop (hence the above pattern for reading until EOF), seek two characters back (which may fail once you reach EOF, my C file functions are a bit rusty these days), write "even" to f1 (which should, if I am wrong about seek after EOF, set input file to "mornieven", and not change it if I am correct). In summary, I don't think the code does what you intend it to do.
I would recommend building up your function. Each one of the following can be written as a program that you should test and finish before going to next step:
read the file safely, and print it out
detect the contents of src, and print the rest of input
save the rest of the input to second file instead of printing
replace src with dest in first file, and ignore the rest (since you open input file with 'rw', this will truncate the rest of input). You may need to do an fseek() to clear the EOF status. Also look at ftell() to record a position that you can jump back to using fseek()
finally, copy in everything you have saved to second file after replacing src with dest (no need to close f1 here. But it is better to open f2 as write, close after copy from first file, and reopen as read to perform the copy back to f1).
In addition, when you need a buffer (such as s1), just use a large enough array for now, but look into malloc() and free() functions to perform dynamic memory allocations for situations like these.
One simple way to do the replace would be to first read in the whole file into a buffer
e.g.
FILE* fpIn = fopen("file.txt","rb");
fseek(fpIn, 0L, SEEK_END);
size_t s = ftell(fpIn);
fseek(fpIn, 0L, SEEK_SET);
void* buf = malloc(s);
fread(buf,s,1,fpIn);
now while writing the file, check for your string
char src[] = "mor";
char dest[] = "even";
int lenSrc = strlen(src);
int lenDest = strlen(dest);
for (char* ch = buf; ch < buf + s; ++ch)
{
if ( !memcmp( ch, src, lenSrc ) )
{
fwrite( dest, 1,lenDest, fpOut );
ch += lenSrc;
}
else
{
fputc( *ch, fp );
}
}
disclaimer: haven't compiled this
You are printing the wrong thing in your output. Print, "ch", not the file pointer.
while(ch!=EOF)
{
ch=getc(f1);
printf("%c",ch);
}
while(ch!=EOF)
{
ch=getc(f2);
printf("%c",ch);
}
Also, f2 is closed at the end during your output. You'll have to reopen it (just like you do with f1.)
At first glance, I see that your code to call fgets is wrong. You have not allocated any memory and you are reading a string into an uninitialized pointer. Read into an array or dynamically allocated memory.
Another problem is that you are declaring ch as char. fgetc() returns an int, and for good reason. It is good to be able to return any possible character or EOF, so EOF shouldn't be a character, so ideally fgetc() returns a bigger type than char.
The upshot is that the loop may well never end, since ch can't possibly hold EOF on some standard implementation. Declare it (and ch1 and ch3) as int.

Resources