Search code examples
cfilenewlinefile-descriptor

Count lines of a file using file descriptor in C


I'm trying to count the number of lines of a file that I'm reading trough a File Descriptor but I don't know what I'm doing wrong because it does not worlk.

This is the code:

fd_openedFile = open(filename, O_RDONLY)        
char *miniBuffer[1];
int lineCounter = 0;
while( read(fd_openedFile, miniBuffer, 1) >0) {
    if (*miniBuffer[0] == '\n')
        lineCounter++;
}

The software never enters the "if" and I've tested a lot of variants that I thought that could work but none of them worked (this is just the one that makes more sense to me).

Any help would be highly apreciated.

Thank you very much!

I have added the full code below:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

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

void err_sys(const char* cadena, int continueExecuting) {
    perror(cadena);
    if (continueExecuting == 0)
        exit(1);
}

int main()
{
    //vars
    char filename[200];
    int fd_output = 1;
    int fd_openedFile = -1;
    int fd_newFile = -1;


    //Ask for the file and open it
    while (fd_openedFile < 0){
        write(fd_output, "Write the filename: ", 20);
        scanf("%s", filename);
        if ((fd_openedFile = open(filename, O_RDONLY)) < 0)
            err_sys("Error opening the original file", 1);
    }

    //Construct the new file's name
    char *partOfOldFilename = strtok(filename, ".");
    char newFileName[208], finalPart[8];
    strcpy(newFileName,  partOfOldFilename);
    strcpy(finalPart, "OUT.txt");
    strcat(newFileName, finalPart);

    //Create the new file
    if ((fd_newFile = open(newFileName, O_WRONLY | O_CREAT)) < 0)
        err_sys("Error opening the new file", 1);

    //Count the number of lines
    char miniBuffer[1];
    int lineCounter = 0;
    while( read(fd_openedFile, &miniBuffer[0], 1) >0) {
        write(fd_output, "R", 1); //To debug
        if (miniBuffer[0] == '\n') {
            lineCounter++;
            write(fd_output, "1", 1); //To debug
        } else {
            write(fd_output, "0", 1); //To debug
            write(fd_output, miniBuffer, 1); //To debug
        }
    }

    lseek(fd_openedFile,0,SEEK_SET);
    write(fd_output, "=========\n", 10); //To debug


    //Count the number of chars per line
    char* charsPerLine[lineCounter];
    lineCounter = 0;
    int charCounter = 0;
    while( read(fd_openedFile, miniBuffer, 1) >0){
        write(fd_output, "C", 1); //To debug
        if (miniBuffer[0] == '\n') {
            *(charsPerLine[lineCounter]) = charCounter +'0';
            lineCounter++;
            charCounter = 0;
            write(fd_output, "1", 1); //To debug
        } else {
            write(fd_output, "0", 1); //To debug
            write(fd_output, miniBuffer, 1); //To debug
            charCounter ++;
        }
    }
    lseek(fd_openedFile,0,SEEK_SET);
    write(fd_output, "END", 4); //To debug

    //Write a copy of the original file starting each line with the number of chars in it
    lineCounter = 0;
    int bufSize = 1;
    char buffer[bufSize];
    //First number write
    if (write(fd_newFile,charsPerLine[lineCounter], bufSize)!=bufSize)
        err_sys("write_error", 0);
    lineCounter++;
    while( read(fd_openedFile, buffer, bufSize) >0){
        if (write(fd_newFile,buffer, bufSize)!=bufSize)
            err_sys("write_error", 0);
        if (buffer[0] == '\n') {
            if (write(fd_newFile,charsPerLine[lineCounter], bufSize)!=bufSize)
                err_sys("write_error", 0);
            lineCounter++;
        }
    }

    //Finish program
    if (close(fd_openedFile)!=0) err_sys("error closing original file's file descriptor", 0);
    if (close(fd_newFile)!=0) err_sys("error closing new file's file descriptor", 0);
    return 0;
}

This codes assumes that the file is a .txt and that at the end of each line there is a "break line" and it is currently in development.

Thanks again.


Solution

  • You're not allocating any memory for miniBuffer which is an array of char pointers. Which isn't really the problem - the problem is that it shouldn't be an array of char pointers in the first place. You only need it to be an array of char like the following.

    char miniBuffer[1];
    

    And the other change then is to check that single element of the array for it being a \n character.

    if (miniBuffer[0] == '\n')
    

    You might find it would be more efficient to read in larger chunks by increasing the size of the array and use functions like strchr to find any \n in the string. You would need to store the amount read returns so you could properly NUL terminate the string though.