Wickkiey
Wickkiey

Reputation: 4632

read() return extra characters from file

I am trying to read text from file to print.. While trying if I give the char buffer size it returns some extra character ..

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(){

    int fd = open("text.txt",O_RDONLY);

    char cbuffer[100];
    int a =0;
    if(fd>0){
        puts("File open");
        ssize_t len = read(fd,cbuffer,sizeof(cbuffer));
        a =printf("%s",&cbuffer);
        printf("\n return data count  %d",a);
    }

    return 0;

}

If instead of

ssize_t len = read(fd,cbuffer,sizeof(cbuffer));

to

ssize_t len = read(fd,cbuffer,10);

returns 10 chars exactly . Can anyone explain why this is happening?

Upvotes: 1

Views: 729

Answers (2)

Iharob Al Asimi
Iharob Al Asimi

Reputation: 53006

Your code has two problems.

  1. Strings in consist of a sequence of non null bytes followed by a null byte. The null byte indicates that there will be no more bytes in the string. It's not impossible but unusual that the null byte would be stored in the file, furthermore if the file is a text file it's almost sure that it will not contain the necessary null byte. If you simply want to display the content of the file you could output data using functions that like read() do not care about the null byte and instead take the number of available bytes as a parameter, example

    ssize_t length = read(fd, cbuffer, sizeof(cbuffer);
    if (length == -1)
        return do_something_an_error_occurred();
    else
        write(STDOU_FILENO, cbuffer, length);
    
  2. You are passing the address of the array to printf()

    printf("%s",&cbuffer);
    

    that's wrong because when printf() finds a "%s" specifier it expects the passed parameter to be a char * pointer but you have passed a pointer to an array of char. An array is automatically converted to a pointer when passed as a parameter, and in general nothing special needs to be done to convert an array to a pointer.

    This is by definition: undefined behavior, and you must note that when you incremente the address of the array it will be incremented by the size of a pointer whereas incrementing the array it self —since it will be a pointer of the type of the array elements— you increment by the size of an element.

ADVICE: Don't use the '\n' at the beginning of a line, it's called the end of line character for a reason. It instructs the printf() to flush the file stream it is writing to, ergo it should be the last character in the format string.

Upvotes: 1

Sourav Ghosh
Sourav Ghosh

Reputation: 134326

This happens because, read() does not null-terminate the output. You need to null-terminate the destination buffer before using it as a string.

Basically passing a non-null terminated char array to printf() as the argument to %s creates undefined behavior as there can be out of bound memory access.

One way of achieving this is to 0-initialize the destination. That way, it will be considered null-terminated after the valid values read and stored by read(). Something like

  char cbuffer[100] = {0};

can help.

That said, change

 printf("%s",&cbuffer);

to

printf("%s",cbuffer);

as %s expects a pointer to a null-terminated array of chars. When you pass the array name to a function, it decays to the pointer to the first element, so you should be ok.

Upvotes: 3

Related Questions