Reading files from a directory

Hi, I'm trying to read files from a directory and process them, but when I run my program, I get the following error message:

terminate called after throwing an instance of 'std::ios_base::failure'
what(): basic_filebuf::underflow error reading the file
Abort

I've been searching through websites for hours and I still don't know what the problem is...any suggestions?

here is the code:


int main(){
ifstream fin;
string dir ;
int num;
DIR *dp;
struct dirent *dirp;

cout << "dir to get files of: ";
cin >> dir;

if((dp = opendir(dir.c_str())) == NULL) {
cout << "Error(" << errno << ") opening " << dir << endl;
return errno;
}

while (dirp = readdir(dp)) {
if(dirp->d_name == "." || dirp->d_name == "..")
continue;
fin.open(dirp->d_name);
fin>>num;
cout<<num<<endl;
}

closedir(dp);

return 0;
}
You are making several mistakes, plus a few style things I'll nag you about ;-)

Line 9: Please use getline( cin, dir ); to get strings from the user.

Line 11: I still don't know why constructs like these are so popular. Make it easy to read:
1
2
  dp = opendir( dir.c_str() );
  if (cp == NULL) {


Line 17: You are trying to compare strings here, but since neither operand is a std::string you are only comparing pointers (char* values to be exact). I'll fix this problem in a moment.

Line 19: You are trying to open a file in another directory using only the simple filename. Hence, it will fail.

Line 20: Again, I think it dangerously presumptive to assume you will open a file with a textual number as the first element... this is where failures occur in software. Do some checking.

Line 22: You didn't close the file. This will cause failure the next time you try to open a file.

To fix those last ones, I suggest you build a file name before line 17 and use it to access the files.
string filepath( dir + "/" + dirp->d_name );

There is one other error that can creep in there: subdirectories. You'll have to use stat() to trap them. Here's a modified version of your program:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <fstream>
#include <iostream>
#include <string>

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

using namespace std;

int main()
  {
  ifstream fin;
  string dir, filepath;
  int num;
  DIR *dp;
  struct dirent *dirp;
  struct stat filestat;

  cout << "dir to get files of: " << flush;
  getline( cin, dir );  // gets everything the user ENTERs

  dp = opendir( dir.c_str() );
  if (dp == NULL)
    {
    cout << "Error(" << errno << ") opening " << dir << endl;
    return errno;
    }

  while ((dirp = readdir( dp )))
    {
    filepath = dir + "/" + dirp->d_name;

    // If the file is a directory (or is in some way invalid) we'll skip it 
    if (stat( filepath.c_str(), &filestat )) continue;
    if (S_ISDIR( filestat.st_mode ))         continue;

    // Endeavor to read a single number from the file and display it
    fin.open( filepath.c_str() );
    if (fin >> num)
      cout << filepath << ": " << num << endl;
    fin.close();
    }

  closedir( dp );

  return 0;
  }

You'll notice that this example skips all subdirectories and also properly handles files that don't have a textual number as the first item.

Hope this helps.
Last edited on
It works! Thanks so much for your help :)
Topic archived. No new replies allowed.