简体   繁体   中英

To count the total number of lines in a file using Unix system call in C

I am a beginner in C language and unix do not have much experience in it. I am trying to count total lines inside the file using unix system call but I am getting no result. My lineCount is always coming out as 0 I do not know why? I want someone to help me figure out the line count if possible.Thanks

int lineCount = 0;
while (*buffer != '\0') // to check the end of the file
{
    read( in_fd, buffer, BUFFERSZ);
    if (*buffer == '\n')
    {
       lineCount++;
    }
}

printf("Linecount: %i \n", lineCount );

Working with open , read and write , is really not much different from working with fopen , fread , and fwrite (or fgets and fprintf ) aside from the burden of any conversions, counting of bytes, and setting created file permission bits being on you. When write writes a value such as 1020 to a file, it is writing the number of bytes you tell it to write, and the number will exist in the file in with the same endianness as your hardware uses.

For example if you have unsigned v = 1020; ( 0x3fc in hex) and then write (fd, &v, sizeof v); , when you look at your file with hexdump or od (or the like), it will contain fc 03 00 00 (assuming your hardware is little-endian). Those are your 4-bytes of an unsigned value 1020 . You can't open the file in a text editor and expect to see ASCII characters, because that isn't what was written to the file.

To find the number of lines in a file using open and read , you basically want to open the file, read the file into a buffer some reasonable number of bytes at a time and count the '\\n' characters in the file.

( note: you will also want to check if the last character read from the file is something other than a '\\n' . If it is you will want to add +1 to your line-count to account for the non-POSIX line end of the final line.)

The only other caveat is to pay attention to the mode (permissions) for any newly created file you open for writing. Otherwise, you will find yourself without access to the newly created file. That is why open provides mode_t mode as the third argument in the case the O_CREAT flag is provided.

If you are going to stay true to only using open, read, write for your program I/O, then you will have to provide error message output to the terminal STDERR_FILENO in the event of an error. You may want a short helper function that will write string messages for that purpose.

Putting the pieces together, you could do something like the following while staying true to your cause. The following code takes the infile and outfile names as the first two arguments to the program, reads infile 65K bytes at a time, counts the '\\n' s in the file and then writes the result to outfile accounting for any non-POSIX line end for the file. writeliteral is provided as a helper for the error messages:

#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

enum { BUFFERSZ = 1 << 16 };    /* 65K buffer size */

void writeliteral (int fildes, const char *s);

int main (int argc, char **argv) {

    if (argc < 3) {
        writeliteral (STDERR_FILENO, "error: insufficient input.\n");
        writeliteral (STDERR_FILENO, "usage: progname infile outfile\n");
        return 1;
    }

    char buf[BUFFERSZ] = "";
    unsigned  i = 0, nlines = 0;
    ssize_t n = 0;
    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    int fd = open (argv[1], O_RDONLY);

    if (fd == -1) {               /* validate file open for reading */
        writeliteral (STDERR_FILENO, "error: infile open failed.\n");
        return 1;
    }

    while ((n = read (fd, buf, sizeof buf)) > 0)  /* read 65k chars */
        for (i = 0; i < n; i++)            /* count newlines in buf */
            if (buf[i] == '\n')
                nlines++;
    if (buf[i - 1] != '\n')       /* account for non-POSIX line end */
        nlines++;

    close (fd); /* close file */

    /* open outfile for writing, create if it doesn't exist */
    if ((fd = open (argv[2], O_WRONLY | O_CREAT, mode)) == -1) {
        writeliteral (STDERR_FILENO, "error: outfile open failed.\n");
        return 1;
    }
    write (fd, &nlines, sizeof nlines);  /* write nlines to outfile */

    close (fd); /* close file */

    return 0;
}

/** write a string literal to 'fildes' */
void writeliteral (int fildes, const char *s)
{
    size_t count = 0;
    const char *p = s;

    for (; *p; p++) {}
    count = p - s;

    write (fildes, s, count);
}

Example Input File

$ nl -ba ../dat/captnjack.txt
     1  This is a tale
     2  Of Captain Jack Sparrow
     3  A Pirate So Brave
     4  On the Seven Seas.

Example Use/Output

$ ./bin/readwrite_lineno ../dat/captnjack.txt ../dat/jacklines.dat
$ hexdump -n 16 -C ../dat/jacklines.dat
00000000  04 00 00 00                                       |....|
00000004

Look it over and let me know if you have any questions. It shows you why you may appreciate the printf family of functions format specifiers even more when you are done.

Your code only checks *buffer for newlines, which is the first character of each BUFFERSZ chunk you read, ie your code doesn't even look at most of the input. (It also doesn't check for end-of-file correctly: you need to look at read 's return value for that.)

Here's a simple solution that emulates fgetc using read :

size_t lines = 0;
char c;
while (read(in_fd, &c, 1) == 1) {
    if (c == '\n') {
        lines++;
    }
}

printf("Linecount: %zu\n", lines);

If you can't use printf either, a quick workaround is:

static void print_n(size_t n) {
    if (n / 10) {
        print_n(n / 10);
    }
    char c = '0' + n % 10;
    write(1, &c, 1);
}

...
write(1, "Linecount: ", strlen("Linecount: "));
print_n(lines);
write(1, "\n", 1);

Reference : Count number of line using C Use the code

FILE *fp = fopen("myfile.txt");
 int ch; 
int count=0;
 do { ch = fgetc(fp); 
if( ch== '\n')
 count++;
 }while( ch != EOF ); 
printf("Total number of lines %d\n",count);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM