Colton
Colton

Reputation: 1297

Differences between writing/reading binary/text in c

I'm working on a client/server program where the client sends/receives files. The files may be text files or binary files. However, I am not sure what changes I need to make, if any, to accommodate for either file type. Basically I am looking to read/write to a file on the server side without caring what type of file it is, I would like to be able to do so without checking what type of file it was. Would code like this work? Why or why not?

Server snippet:

//CREATING/WRITING TO A FILE
//we are ready to begin reading data from the client, and storing it 
int fd = open(pathname, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR);
while(nbytes < bytes)
{
    //only read the neccessary # of bytes: the remaining bytes vs max buffer size
    int min_buffer = (bytes - nbytes) < BUFFER_SIZE ? (bytes - nbytes) : BUFFER_SIZE;
    length = recv( client->client_socket, contents, min_buffer, 0);

    if(fd < 0) //the fd is bad, but we need to continue reading bytes anyway
    {
        nbytes += length;
        continue;
    }

    if(length <= 0)
        break;//string empty or error occurred...this error means the client closed?

    if(write(fd, contents, min_buffer) != min_buffer)
    {
        //printf("There was an error writing to the file.\n");
    }
    else
    {       
        nbytes += length;
    }
}


//READING A STORED FILE AND SENDING THE DATA TO CLIENT
int fd = open(pathname, O_RDWR, S_IRUSR | S_IWUSR);
if(fd >= 0)
{
    while(bytes > 0)
    {
        bytes = read(fd, buffer,  BUFFER_SIZE );

        if(bytes > 0)//we have read some bytes
        {
            //send the client the data
            write(client->client_socket, buffer, bytes);
        }
        else if(bytes < 0)
        {
            //some error occured
            write( client->client_socket, "ERROR: Could not read\n", 22);   
            return;
        }
    }
}

So if the client sends a binary file vs a text file, would this code cause issues? (We can assume the client knows what type of file to expect.)

Note: Another confusing detail about this is that there are tutorials for writing/reading binary files in c that didn't seem to have any real differences over regular files, which is what lead me here.

Upvotes: 3

Views: 4170

Answers (2)

A Boyd
A Boyd

Reputation: 1

I tore my hair out for a day over a binary/text file issue. I was outputting binary data into "files" (apparently text files ... after years and years of C I'd always thought a file was a file) and kept getting spurious characters inserted into the output. I went so far as to download a new compiler but had the same problem. The issue? When I output hex A using any of the family of fprint statements, hex D was being inserted. Yes, line feed characters -- A -- were being replaced by carriage return/line feed -- DA. It's a legacy "end of line" issue based on how different systems have developed. The tough part of finding the problem was realizing A was being interpreted as more than just a binary field, but actually being recognized as a line feed.

Upvotes: -1

deviantfan
deviantfan

Reputation: 11434

Just do everything with "binary" files. Linux has no difference between "text" and "binary" in a file on OS level, there are just files with bytes in it. Ie. expect that a file contains every possible byte value, and don´t write different code for different kinds of content.

There is a difference in Windows: Text mode in Windows means that a line break (\n) in the program gets converted to/from \r\n when writing to / reading from a file. The written text file read in binary mode will contain this two bytes instead of the original \n and vice-versa. (Additionally, MS isn´t very clear in the documentation that this is the only difference, it can confuse beginners easily.)

If you use standard C fopen and fclose instead of Linux-specific open etc., you can specify to open a file in binary or text mode (on Linux too). This is because code with fopen should work on Windows and Linux without any OS-specific changes; but what you choose in fopen doesn´t matter when running on Linux (which can be verified by reading the source code of fopen etc.)

And about the sockets:
Linux: No difference (again)
Windows: No difference too. There are just bytes, and no strange line break conversions.

Upvotes: 11

Related Questions