Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clearest way to read and print .txt file lines in C

There are a bunch of ways describing how to use various methods to print out lines of a text file on this site:

  • Posix-style,
  • reading IP addresses,
  • Fixed line length.

They all seem to be tailored to a specific example.

It would be great to have the Clearest and Most Concise and Easiest way to simply: print each line of any text file to the screen. Preferably with detailed explanations of what each line does.

Points for brevity and clarity.

like image 783
Dlinet Avatar asked Dec 28 '12 00:12

Dlinet


People also ask

How do you read and print the contents of a file in C?

Open a file using the function fopen() and store the reference of the file in a FILE pointer. Read contents of the file using any of these functions fgetc(), fgets(), fscanf(), or fread(). File close the file using the function fclose().

Can you print .txt files?

Once you've got Notepad's settings right, try this trick: Open Windows Explorer and right-click a text file. On the context menu that appears, click Print. You no longer need to open Notepad first to tell it your preferences. Notepad remembers them for you.

How do I read a .TXT file?

How to open a TXT file. You can open a TXT file with any text editor and most popular web browsers. In Windows, you can open a TXT file with Microsoft Notepad or Microsoft WordPad, both of which come included with Windows.


1 Answers

#include <stdio.h>

static void cat(FILE *fp)
{
    char   buffer[4096];
    size_t nbytes;
    while ((nbytes = fread(buffer, sizeof(char), sizeof(buffer), fp)) != 0)
         fwrite(buffer, sizeof(char), nbytes, stdout);
}

int main(int argc, char **argv)
{
    FILE *fp;
    const char *file;
    while ((file = *++argv) != 0)
    {
        if ((fp = fopen(file, "r")) != 0)
        {
            cat(fp);
            fclose(fp);
        }
    }
    return(0);
}

The cat() function is not strictly necessary, but I'd rather use it. The main program steps through each command line argument and opens the named file. If it succeeds, it calls the cat() function to print its contents. Since the call to fopen() does not specify "rb", it is opened as a text file. If the file is not opened, this code silently ignores the issue. If no files are specified, nothing is printed at all.

The cat() function simply reads blocks of text up to 4096 bytes at a time, and writes them to standard output ('the screen'). It stops when there's no more to read.

If you want to extend the code to read standard input when no file is specified, then you can use:

if (argc == 1)
    cat(stdin);
else
{
    ...while loop as now...
}

which is one of the reasons for having the cat() function written as shown.

This code does not pay direct attention to newlines — or lines of any sort. If you want to process it formally one line at a time, then you can do several things:

static void cat(FILE *fp)
{
    char buffer[4096];
    while (fgets(buffer, sizeof(buffer), fp) != 0)
         fputs(buffer, stdout);
}

This will read and write one line at a time. If any line is longer than 4095 bytes, it will read the line in two or more operations and write it in the same number of operations. Note that this assumes a text file in a way that the version using fread() and fwrite() does not. On POSIX systems, the version with fread() and fwrite() will handle arbitrary binary files with null bytes ('\0') in the data, but the version using fgets() and fputs() will not. Both the versions so far are strictly standard C (any version of the standard) as they don't use any platform-specific extensions; they are about as portable as code can be.

Alternatively again, if you have the POSIX 2008 getline() function, you can use that, but you need #include <stdlib.h> too (because you end up having to release the memory it allocates):

static void cat(FILE *fp)
{
    char *buffer = 0;
    size_t buflen = 0;
    while (getline(&buffer, &buflen, fp) != -1)
         fputs(buffer, stdout);
    free(buffer);
}

This version, too, will not handle binary data (meaning data with null bytes in it). It could be upgraded to do so, of course:

static void cat(FILE *fp)
{
    char *buffer = 0;
    size_t buflen = 0;
    ssize_t nbytes;
    while ((nbytes = getline(&buffer, &buflen, fp)) != -1)
         fwrite(buffer, sizeof(char), nbytes, stdout);
    free(buffer);
}

The getline() function reports how many bytes it read (there's a null byte after that), but the fwrite() function is the only one that takes a stream of arbitrary bytes and writes them all to the given stream.

like image 116
Jonathan Leffler Avatar answered Nov 04 '22 02:11

Jonathan Leffler