Random integers coming from the "write" system call are not recognized from the "read" system call in C

StackOverflow https://stackoverflow.com/questions/22976647

Question

I am trying to write a fixed number of random integers into a file, using the system call "write", and then check if they are written properly. In order to do this, I call the "read" function, then I read all the file content, integer by integer and I print them into another file.

The problem is that although the write function writes properly the random integers (500 in size), the read function is able to extract e.g 200 of them and then it returns garbage for the rest 300. Sometimes, it returns only 10 of them. Every time I run the code, it has a different behavior.

I have checked that the "write" function writes all the numbers correctly by printing them to another file (e.g file1). But, printing the numbers that the "read" function returns (e.g. file2) showed me that they are not all the same.

I realized that if I use a single number (e.g. 5) instead of a random integer, it all works fine. I googled a lot, I checked if I open/close the files properly and I could not solve the problem.

Here is my code in C. I removed some error checks in order to show you a small script. Can you please help me?

int main()
{
    srand ( time(NULL) );

    // write
    int fd = open("file_test_1", O_CREAT | O_WRONLY);
    int val;
    if (fd != -1) {
        for(int i=0;i<500;i++){
            val = (int) rand()%500;
           // val = 5;
            write(fd, &val, sizeof(val));
        }
    }
    close(fd);

    FILE * file_check;
    file_check=fopen("file_test_1_check","w");

   // test read
    fd = open("file_test_1", O_RDONLY);
    int new_val;
    int x;
    if (fd != -1) {
        while(  ( x = read(fd, &new_val, sizeof(new_val)) )>0 ){
            fprintf(file_check,"%d\t\t%d\n",new_val, x);
        }

    }
    close(fd);
    fclose(file_check);
    return 0;
}
Was it helpful?

Solution

When you use O_CREAT to open a file, you need to set file permissions for subsequent users. You do that by specifiying the pmode, ie OR ing the combination of the flags S_IREAD S_IWRITE (go ahead and use both). Also since you're writing a binary, it wouldn't hurt informing the system with O_BINARY. So the correct open would be :

int fd = open("file_test_1", O_BINARY | O_CREAT | O_WRONLY | S_IREAD);

Now, when you reopen that file, you really need to open it in binary form, so the correct subsequent open would be :

fd = open("file_test_1", O_RDONLY | O_BINARY);

OTHER TIPS

Your first open call is wrong. Per the man page, when you pass O_CREAT in the oflag argument to open, a third mode argument is required. This will be the access mode for the file. On my system, open is seeing 0 for the omitted third argument (left-over value in a register or on the stack), so the next open (to read the file) fails.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top