0

I need to loop trough a directory, data and read each file, that meets certain conditions, in a string and do something with it. For some reason it fails after the fseek call (the output is only the name of the first file in the directory).

Any idea what am I doing wrong?

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>

void doAlgorithm(char *input) {
    printf("%s\n", input);
}

int main(int argc, char** argv) {
    struct dirent *dir;
    DIR *d = opendir("data");
    FILE *file;
    while ((dir = readdir(d)) != NULL) {
        if (strlen(dir->d_name) > 6 && dir->d_name[6] == 'i') {
            printf("Filename: %s\n", dir->d_name);
            file = fopen(dir->d_name, "r");
            fseek(file, 0, SEEK_END);
            long length = ftell(file);
            fseek(file, 0, SEEK_SET);
            printf(", Filesize: %ld\n", length);

            char *buffer = malloc(length + 1);
            fread(buffer, 1, length, file);
            buffer[length] = '\0';

            fclose(file);
            doAlgorithm(buffer);
        }
    }
    closedir(d);
    return (EXIT_SUCCESS);
}
Petr Kroupa
  • 53
  • 3
  • 8
  • `ftell` returns a `long` int is too small – Seek Addo Apr 14 '17 at 13:23
  • You're also failing to check return values all over the place. Just because you asked for `length` bytes doesn't mean you got them for instance. – ShadowRanger Apr 14 '17 at 13:41
  • ok i fixed that, but it still doesn't change anything, program still doesn't work properly after the fseek() call. By the way i'm running this on windows if it matters. – Petr Kroupa Apr 14 '17 at 13:41
  • The problem is there is something wrong going on with the fseek call, if i try to print the fseek or ftell return values it doesn't print anything – Petr Kroupa Apr 14 '17 at 13:45
  • 1
    your code here fails to open the file because it doesn't have the full path of the file `file = fopen(dir->d_name, "r");` pass in the full path to the file to open it and it will work. – Seek Addo Apr 14 '17 at 13:54
  • When you do `fopen`, you pass only the filename as parameter, it should be "data/filename". – letmutx Apr 14 '17 at 13:57
  • great that was exactly the problem, thank you very much – Petr Kroupa Apr 14 '17 at 14:11

1 Answers1

0

Your problem is that you file = fopen(dir->d_name, "r"); doesn't know where that file is in the directory. you need to give it the full path. You can do this;

    struct dirent *dir;
   // put the directory path here. on windows is \ instead of /
    char *path = "/Users/adnis/CLion/Stackoverflow/testdir";
    char *slash = "";
    DIR *d = opendir(path);
    FILE *file;
        while ((dir = readdir(d)) != NULL) {
       if (strlen(dir->d_name) > 6 && dir->d_name[6] == 'i') {
                printf("Filename: %s\n", dir->d_name);
                int length = strlen(path);
        /*check if the path already contains a '/' at 
          the end before joining the filename to the directory*/

                if(path[strlen(path)-1] != '/'){ //on windows is '\'
                   slash = "/";
                }

                length += strlen(dir->d_name)+2;
     // allocate memory for the new path
     // and make sure we have enough memory.
                char *newpath = malloc(length);

                assert(newpath != NULL);

                snprintf(newpath,length,"%s%s%s",path,slash,dir->d_name);

                file = fopen(newpath, "r");
                if(file == NULL){
                    fprintf(stderr, "fopen: %s\n", strerror(errno));
                    break;
                }
                fseek(file, 0, SEEK_END);
                long len = ftell(file);
                fseek(file, SEEK_SET, 0);

                char *buffer = malloc(len + 1);
                fread(buffer, 1, len, file);
                buffer[strlen(buffer)] = '\0';

                printf("%s \n",buffer);
                fclose(file);
            }
        }
        closedir(d);
        return (EXIT_SUCCESS);

I suggest that when reading directory you have to also try and avoid reading "." and ".." since they are just current directory and previous directory. something like this will help. In your while loop

if(strcmp(dir->d_name,".") == 0 || strcmp(dir->d_name,"..") == 0)
            continue;
Seek Addo
  • 1,871
  • 2
  • 18
  • 30