简体   繁体   中英

Unix HEAD command implementation in C fails on larger lines

I am currently implementing the Unix HEAD command with C and using only system functions. So far, it works perfectly on files, which have lines with less length than the one that I specified for my buffer :

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define LINES_TO_READ 10
#define BUFF_SIZE 4096

int main(int argc, char const *argv[]) {
    for (ssize_t i = 1; i < argc; i++) {
        const char *filename = argv[i];

        int fd = open(filename, O_RDONLY);

        if (fd < 0) {
            perror("open");
            return -1;
        }

        char ch, buffer[BUFF_SIZE];
        size_t index = 0, lines = 1;
        ssize_t rresult, wresult;

        // Read the file byte by byte
        while ((rresult = read(fd, &ch, 1)) != 0) {
            if (rresult < 0) {
                perror("read");
                return -1;
            }

            // Check if the current character is a new line (the line ends here)
            if (ch == '\n') {
                buffer[index] = ch;
                buffer[index + 1] = '\0';
                ch = 0;
                index = 0;

                // Print the line
                wresult = 0;
                ssize_t buffer_length = strlen(buffer);
                while (wresult != buffer_length) {
                    ssize_t res = write(STDOUT_FILENO, buffer + wresult, buffer_length - wresult);

                    if (wresult < 0) {
                        perror("write");
                        return -1;
                    }

                    wresult += res;
                }

                // Stop if we read 10 lines already
                if (lines == LINES_TO_READ) {
                    break;
                }

                lines++;
            } else {
                buffer[index++] = ch;
            }
        }

        if (close(fd) < 0) {
            perror("close");
            return -1;
        }
    }

    return 0;
}

And it works on files, which have a line length with less than BUFF_SIZE (as now set, 4096 ).

How to avoid this and make it work for whatever the line length is?

Don't read one byte at a time. Read a chunk (4096 or 8192 bytes are reasonable sizes, or use PIPE_BUF (from limits.h)) into a buffer. Output each character while counting newlines. If you print enough newlines, terminate. If you reach the end of the buffer and haven't printed enough lines, read more data into the buffer.

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