Append one file to another?

Discussion in 'C Programming' started by Ishmael, Jun 23, 2009.

  1. Ishmael

    Ishmael Guest

    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!
     
    Ishmael, Jun 23, 2009
    #1
    1. Advertising

  2. Ishmael

    Doug Miller Guest

    In article <>, Ishmael <> wrote:
    >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
     
    Doug Miller, Jun 23, 2009
    #2
    1. Advertising

  3. Ishmael

    PariahCarey Guest

    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.
     
    PariahCarey, Jun 23, 2009
    #3
  4. Ishmael

    user923005 Guest

    On Jun 22, 6:41 pm, Ishmael <> wrote:
    > 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
    */
     
    user923005, Jun 23, 2009
    #4
  5. user923005 <> writes:
    > On Jun 22, 6:41 pm, Ishmael <> wrote:
    >> 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.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jun 23, 2009
    #5
  6. Ishmael

    user923005 Guest

    On Jun 23, 12:39 am, Keith Thompson <> wrote:
    [snip]
    > 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
    */
     
    user923005, Jun 23, 2009
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. June Moore

    Append one array to another array

    June Moore, Oct 28, 2004, in forum: Java
    Replies:
    20
    Views:
    68,062
    HeidelbergMan
    Jul 6, 2007
  2. Replies:
    8
    Views:
    620
    John Machin
    Jul 13, 2005
  3. HYRY
    Replies:
    10
    Views:
    608
    Bruno Desthuilliers
    Sep 26, 2007
  4. Victor Bazarov

    Re: Append one enum to another?

    Victor Bazarov, May 8, 2009, in forum: C++
    Replies:
    7
    Views:
    519
    Pascal J. Bourguignon
    May 15, 2009
  5. Robert Cohen
    Replies:
    3
    Views:
    275
    Andrew Durstewitz
    Jul 15, 2003
Loading...

Share This Page