Append one file to another?

I

Ishmael

Is there an easy way to append the contents of one file to another?
Currently, I have to do the following steps explicitly:

1) Read all data from file A into RAM (fopen, fseek, fread)
2) Write all data to file B (fwrite).

Is there a built-in way of doing this? As I understand it, 'memcpy'
only copies blocks of memory from one part of RAM to another, not
between files.

Thanks for your help!
 
D

Doug Miller

Is there an easy way to append the contents of one file to another?
Yes.

Currently, I have to do the following steps explicitly:

1) Read all data from file A into RAM (fopen, fseek, fread)
2) Write all data to file B (fwrite).

Is there a built-in way of doing this?

Built into the operating system, sure. Is there some reason you need to do
this in a C program?

Under any Microsoft OS, the following command will work:
type file1 >> file2

Unix:
cat file1 >> file2
 
P

PariahCarey

Thanks a lot! I hadn't thought of using system commands. Since I'm
trying to write code that will work on both Linux and Windows, it
might be safer to just stick with the fread/fwrite method. I wonder
how the system call compare in terms of speed. Anyway, thanks for the
advice.
 
U

user923005

Is there an easy way to append the contents of one file to another?
Currently, I have to do the following steps explicitly:

1) Read all data from file A into RAM (fopen, fseek, fread)
2) Write all data to file B (fwrite).

Is there a built-in way of doing this?  As I understand it, 'memcpy'
only copies blocks of memory from one part of RAM to another, not
between files.

Assuming text input files, with no line longer than one million
characters, something along these lines should work:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static char string[1000000];

void catstrings(FILE * in, FILE * out)
{
setvbuf(in, NULL, _IOFBF, 1024 * 16);
setvbuf(out, NULL, _IOFBF, 1024 * 16);

while (fgets(string, sizeof string, in)) {
fputs(string, out);
}
}

int main(int argc, char **argv)
{
FILE *in = stdin;
FILE *out = stdout;
clock_t start,
end;
static const double cps = 1.0 / CLOCKS_PER_SEC;
if (argc > 1) {
in = fopen(argv[1], "r");
if (in == NULL) {
printf("Error opening %s\n", argv[1]);
exit(EXIT_FAILURE);
}
}
if (argc > 2) {
out = fopen(argv[2], "a");
if (out == NULL) {
printf("Error opening %s\n", argv[2]);
exit(EXIT_FAILURE);
}
}
start = clock();
catstrings(in, out);
end = clock();
printf("big buffer cat using fgets took %f seconds\n", (end -
start) * cps);
fflush(NULL);
return 0;
}

/*
W:\tmp>dir bible.txt
Volume in drive W has no label.
Volume Serial Number is 0890-87CA

Directory of W:\tmp

03/25/2008 08:15 PM 4,047,392 bible.txt
1 File(s) 4,047,392 bytes
0 Dir(s) 64,396,148,736 bytes free

W:\tmp>fatcat bible.txt b.txt
big buffer cat using fgets took 0.535000 seconds

W:\tmp>dir b.txt
Volume in drive W has no label.
Volume Serial Number is 0890-87CA

Directory of W:\tmp

06/22/2009 09:08 PM 4,077,775 b.txt
1 File(s) 4,077,775 bytes
0 Dir(s) 64,392,069,120 bytes free

W:\tmp>fatcat bible.txt b.txt
big buffer cat using fgets took 0.470000 seconds

W:\tmp>dir b.txt
Volume in drive W has no label.
Volume Serial Number is 0890-87CA

Directory of W:\tmp

06/22/2009 09:08 PM 8,155,550 b.txt
1 File(s) 8,155,550 bytes
0 Dir(s) 64,387,989,504 bytes free

W:\tmp>fatcat bible.txt b.txt
big buffer cat using fgets took 0.478000 seconds

W:\tmp>dir b.txt
Volume in drive W has no label.
Volume Serial Number is 0890-87CA

Directory of W:\tmp

06/22/2009 09:08 PM 12,233,325 b.txt
1 File(s) 12,233,325 bytes
0 Dir(s) 64,383,913,984 bytes free
*/
 
K

Keith Thompson

user923005 said:
Is there an easy way to append the contents of one file to another?
Currently, I have to do the following steps explicitly:

1) Read all data from file A into RAM (fopen, fseek, fread)
2) Write all data to file B (fwrite).

Is there a built-in way of doing this?  As I understand it, 'memcpy'
only copies blocks of memory from one part of RAM to another, not
between files.

Assuming text input files, with no line longer than one million
characters, something along these lines should work:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static char string[1000000];

void catstrings(FILE * in, FILE * out)
{
setvbuf(in, NULL, _IOFBF, 1024 * 16);
setvbuf(out, NULL, _IOFBF, 1024 * 16);

Why 16 kilobytes in partiuclar?
while (fgets(string, sizeof string, in)) {
fputs(string, out);
}
}
[snip]

That will work equally well with lines longer than one million
characters; long lines will simply be processed in two or more chunks.

Which raises the question of why you need such a big buffer anyway, or
why you'd use fgets and fputs rather than fread and fwrite.

For that matter, you could just use fgetc and fputc and copy one
character at a time. Both are normally defined as macros that will
buffers of whatever size makes sense for the system. In fact, it
would be interesting to write two versions of the program, one that
uses fgetc and fputc, and another than copies, say, 16 kbytes as a
time, and compare their performance.
 
U

user923005

For that matter, you could just use fgetc and fputc and copy one
character at a time.  Both are normally defined as macros that will
buffers of whatever size makes sense for the system.  In fact, it
would be interesting to write two versions of the program, one that
uses fgetc and fputc, and another than copies, say, 16 kbytes as a
time, and compare their performance.

I did that before and posted it here.

In fact, the snippet that I posted was a slightly modified excerpt
from that code. The original does not actually concatenate, since it
opens the output for write instead of append.

Here is the previous code:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static char string[1024 * 16];

void catfilebufferfgets(FILE * in, FILE * out)
{
setvbuf(in, NULL, _IOFBF, 1024 * 16);
setvbuf(out, NULL, _IOFBF, 1024 * 16);

/* Get characters (ERROR PRONE: {what if string > 16K}) */
while (fgets(string, sizeof string, in)) {
fputs(string, out);
}
}

void catfilebuffer(FILE * in, FILE * out)
{
register int num_char;

setvbuf(in, NULL, _IOFBF, 1024 * 16);
setvbuf(out, NULL, _IOFBF, 1024 * 16);

/* Get characters */
while ((num_char = getc(in)) != EOF) {
/* Print to standard output */
putc(num_char, out);
}
}

void catfilenobuff(FILE * in, FILE * out)
{
register int num_char;

/* Get characters */
while ((num_char = getc(in)) != EOF) {
/* Print to standard output */
putc(num_char, out);
}
}

int main(int argc, char **argv)
{
FILE *in = stdin;
FILE *out = stdout;
clock_t start,
end;
static const double cps = 1.0 / CLOCKS_PER_SEC;
if (argc > 1) {
in = fopen(argv[1], "r");
if (in == NULL) {
printf("Error opening %s\n", argv[1]);
exit(EXIT_FAILURE);
}
}
if (argc > 2) {
out = fopen(argv[2], "w");
if (out == NULL) {
printf("Error opening %s\n", argv[2]);
exit(EXIT_FAILURE);
}
}
start = clock();
catfilenobuff(in, out);
end = clock();
printf("standard cat took %f seconds\n", (end - start) * cps);
rewind(in);
fclose(out);
if (argc > 2) {
out = fopen(argv[2], "w");
if (out == NULL) {
printf("Error opening %s\n", argv[2]);
exit(EXIT_FAILURE);
}
} else
out = stdout;
start = clock();
catfilebuffer(in, out);
end = clock();
printf("big buffer cat took %f seconds\n", (end - start) * cps);
rewind(in);
fclose(out);
if (argc > 2) {
out = fopen(argv[2], "w");
if (out == NULL) {
printf("Error opening %s\n", argv[2]);
exit(EXIT_FAILURE);
}
} else
out = stdout;
start = clock();
catfilebufferfgets(in, out);
end = clock();
printf("big buffer cat using fgets took %f seconds\n", (end -
start) * cps);
fflush(NULL);
return 0;
}
/*
C:\tmp>cat dict.sql dict.out
standard cat took 2.062000 seconds
big buffer cat took 2.016000 seconds
big buffer cat using fgets took 0.203000 seconds
*/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top