Thread: Reading File in C

  1. #1
    Registered User
    Join Date
    Feb 2019
    Posts
    69

    Reading File in C

    Hey,

    unfortunately the following code does not work:

    Code:
     #include "test.h"
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main(int argv, char* args[]){
        char filename[] = "mydata.txt";
        FILE *file = fopen(filename, "a+");
        fprintf(file,"This was a triumph.\n");
        char buf[50];
        printf("%lu \n",fread(buf, sizeof(buf), 50, file));
        printf("%s",buf);
        fclose(file);
    }


    I am wondering about 2 things:

    In the documentation of fread it is stated that it want the pointer to the buffer. So why I am not ought to:


    Code:
    printf("%lu \n",fread(&buf, sizeof(buf), 50, file));
    give buf as a reference?
    Furthermore I am wondering why 0 bytes are read.

    Which leads me to the last question:
    When should I use fopen, fwrite... and when open,write,...

    Thank you!

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    unfortunately the following code does not work:
    You may want to consider doing a couple of things. First check that the file opened correctly. Second rewind() the file after you write the data.

    In the documentation of fread it is stated that it want the pointer to the buffer. So why I am not ought to:
    Because the name of an array acts like a pointer so you don't need to de-reference that pointer.

    Furthermore I am wondering why 0 bytes are read.
    Probably because the read failed.

    Be careful with that fread(), do you realize that you're trying to read more characters than will fit into your array? What do you think sizeof(buf) returns? Now multiply that by 50.

    When should I use fopen,
    Most of the time.

    fwrite...
    Rarely, and then only when you opened the file in binary mode. Remember fwrite() and fread() are considered unformatted operations you normally would use fprintf(), fscanf(), fgets() instead. Note that the fwrite() and fread() are normally used together and fprintf() followed by fcanf() of fgets() are also normally used together. Mixing unformatted operations with formatted operations is usually not recommended.

    open,write
    Again rarely. Remember these functions are not standard C functions (they are part of the POSIX standard) and are not available to all systems. Only use them when you know they will be available and when you really need the lower level of control.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Each file has a position indicator which is the point in the file where the next read/write will take place.

    So having just appended a line (that's what the a+ mode means), you're stuck at the end of the file.

    If you want to read something, you need to seek.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argv, char* args[]){
        char filename[] = "foo.txt";
        FILE *file = fopen(filename, "a+");
        fprintf(file,"This was a triumph.\n");
        fflush(file);  // always a good idea when switching from writing to reading
        fseek(file,0,SEEK_SET);
        char buf[50];
        printf("%lu \n",fread(buf, sizeof(buf), 50, file));
        printf("%s",buf);
        fclose(file);
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Feb 2019
    Posts
    69
    Quote Originally Posted by Salem View Post
    Each file has a position indicator which is the point in the file where the next read/write will take place.

    So having just appended a line (that's what the a+ mode means), you're stuck at the end of the file.

    If you want to read something, you need to seek.
    [/code]
    Should not the read start at the beginning. I do not see the problem?

    Running your code again and again (4 times) throws a error in this unpleasant peace of assembly code, if you read more than you can...
    How to avoid this?

    Code:
    libsystem_kernel.dylib`__pthread_kill:
        0x7fff7ad7f234 <+0>:  movl   $0x2000148, %eax          ; imm = 0x2000148 
        0x7fff7ad7f239 <+5>:  movq   %rcx, %r10
        0x7fff7ad7f23c <+8>:  syscall 
    ->  0x7fff7ad7f23e <+10>: jae    0x7fff7ad7f248            ; <+20>
        0x7fff7ad7f240 <+12>: movq   %rax, %rdi
        0x7fff7ad7f243 <+15>: jmp    0x7fff7ad793b7            ; cerror_nocancel
    0x7fff7ad7f248 <+20>: retq   
    Last edited by SuchtyTV; 02-13-2019 at 10:37 AM.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > How to avoid this?
    Well you need to make sure the buffer returned by fread() is \0 terminated, if you're just going to try and print it with printf("%s")

    > fread(buf, sizeof(buf), 50, file)
    Also, it's NOT 50 in both parameters.

    Either of these.
    fread(buf, 1, sizeof(buf), file)
    fread(buf, sizeof(buf), 1, file)
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    Quote Originally Posted by SuchtyTV
    Should not the read start at the beginning. I do not see the problem?
    C requires a file positioning function to be used between output and input on a read/write stream, even if it's a no-op like fseek(file, 0, SEEK_CUR).
    Code:
    #include <stdio.h>
     
    int main() {
        char buf[1000];
        FILE *file = fopen("foo.txt", "a+");
     
        fprintf(file, "This was a triumph.\n");
     
        fseek(file, 0, SEEK_SET);
        buf[fread(buf, 1, sizeof(buf), file)] = '\0';
        printf("%s-----\n", buf);
     
        // append mode automatically positions to the end before writing
        fprintf(file, "A second line.\n");
     
        fseek(file, 0, SEEK_SET);
        buf[fread(buf, 1, sizeof(buf), file)] = '\0';
        printf("%s-----\n", buf);
     
        fclose(file);
     
        return 0;
    }
    A little inaccuracy saves tons of explanation. - H.H. Munro

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > buf[fread(buf, 1, sizeof(buf), file)]
    Beware that buf[sizeof(buf)] is actually out of bounds.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    Quote Originally Posted by Salem View Post
    > buf[fread(buf, 1, sizeof(buf), file)]
    Beware that buf[sizeof(buf)] is actually out of bounds.
    Nice catch. I'm used to using the text functions (like fgets) with text files and they leave space for the null char.
    So those freads should be:
    Code:
    buf[fread(buf, 1, sizeof(buf) - 1, file)] = '\0';
    A little inaccuracy saves tons of explanation. - H.H. Munro

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 11-27-2013, 12:24 PM
  2. Replies: 3
    Last Post: 11-28-2012, 09:16 AM
  3. Replies: 3
    Last Post: 07-17-2011, 03:51 AM
  4. Replies: 13
    Last Post: 05-31-2009, 11:30 AM
  5. Reading flat file and generating tagged file
    By AngKar in forum C# Programming
    Replies: 4
    Last Post: 03-24-2006, 08:29 AM

Tags for this Thread