Searching Directory for .CSV file and Searching file

Pages: 12
I am storing each row of the CSV in a string.
I.E: row1 outputs: John, More, 33, 80
How can i search through this string and do a if (33 <50) output "error". if 80 >50 output "no error. "Basically, each piece of data in the string is going to be compared to some tests.
Thanks.

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
50
51
52
53
54
55
56
57
#include <stdio.h>
#include <dirent.h>
#include <iostream>
#include <string>
#include <fstream>


using namespace std;

int main(void)
{
	string row1;
	string row2;
	string row3;
	string row4;
	// Pointer for directory entry
	struct dirent *de;

	// opendir() returns a pointer of DIR type. 
	DIR *dr = opendir(".");

	// opendir returns NULL if couldn't open directory
	if (dr == NULL)
	{
		cout << "Could not open current directory" << endl;
		cin.get();
		return 0;
	}

	while ((de = readdir(dr)) != NULL)
	{
		string name(de->d_name);

		// Search directory for all files ending in .csv
		if (name.size() > 4 && name.substr(name.size() - 4) == ".csv")
		{
			cout << name << ":\n";
			ifstream fin(name); //bring in file
			string line;
			getline(fin, row1);
			 
			getline(fin, row2);
			getline(fin, row3);
			getline(fin, row4);
			cout << row1 << endl;
			cout << row2 << endl;
			cout << row3 << endl;
			cout << row4 << endl;

		}

	}
	cin.get();
	closedir(dr);

	return 0;
}
Last edited on
What operating system are you using? Wildcard *.* is not normally used on Unix.
@kbw, I don't think it's a wildcard. It's just the current directory "."
And he's presumably on Windows since he mentions dragging a file onto another file to run the program, although he's saying it backwards. He needs to drag the directory onto the exe file. He also mentions "specially importing" dirent.h, which would not be necessary on Linux (whatever "specially importing" means).

@akarbarz, Can you compile this 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
#include <iostream>
#include <dirent.h>
using namespace std;

int main(int argc, char **argv)
{
    if (argc != 2) {
        cerr << "Usage: progname <DIRECTORY>\n";
        cin.get();
        return 0;
    }

    DIR *dr = opendir(argv[1]);
    if (dr == NULL)  
    {
        cerr << "Could not open current directory\n";
        cin.get();
        return 0;
    }

    struct dirent *de;  
    while ((de = readdir(dr)) != NULL)
        cout << de->d_name << '\n';

    closedir(dr);

    cin.get();
    return 0;
}

If you drag a directory onto it, does it display the file names in the directory?
To find the .csv files, just check that the name ends in .csv.
Then open the file and do what you will.

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
#include <iostream>
#include <fstream>
#include <string>
#include <dirent.h>
using namespace std;

int main(int argc, char **argv)
{
    if (argc != 2) {
        cerr << "Usage: progname <DIRECTORY>\n";
        cin.get();
        return 0;
    }

    DIR *dr = opendir(argv[1]);
    if (dr == NULL)  
    {
        cerr << "Could not open current directory\n";
        cin.get();
        return 0;
    }

    struct dirent *de;  
    while ((de = readdir(dr)) != NULL) {
        string name(de->d_name);
        if (name.size() > 4 && name.substr(name.size()-4) ==".csv") {
            cout << name << ":\n";
            ifstream fin(name);
            string line;
            while (getline(fin, line)) {
                cout << '\t' << line << '\n';
            }
        }
    }

    closedir(dr);

    cin.get();
    return 0;
}

Last edited on
The reason I asked is because I would use fts rather than dir. It deals with directory loops and crap like that.

https://man.openbsd.org/fts.3
https://linux.die.net/man/3/fts_open
https://docs.oracle.com/cd/E88353_01/html/E37843/fts-open-3c.html
Last edited on
I am using Windows. By "specially" importing I meant that dirent.h is a Linux thing and I had to find a version from github to download and add to my VS header files.
@tpb It compiles but it only outputs ""Usage: progname <DIRECTORY>"
And you were correct "." is just the current directory. In the program I would like to just drop the .exe into a folder with a bunch of files with .csv files in them and check them for errors.
i got one of them to compile and only output the .csv files name!

[code]
#include <stdio.h>
#include <dirent.h>
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

int main(void)
{
// Pointer for directory entry
struct dirent *de;

// opendir() returns a pointer of DIR type.
DIR *dr = opendir(".");

// opendir returns NULL if couldn't open directory
if (dr == NULL)
{
cout << "Could not open current directory" << endl;
cin.get();
return 0;
}

while ((de = readdir(dr)) != NULL)
{
string name(de->d_name);
if (name.size() > 4 && name.substr(name.size() - 4) == ".csv")
{
cout << name << ":\n";
cin.get();
ifstream fin(name);
string line;
while (getline(fin, line))
{
cout << '\t' << line << '\n';
}
}

}
cin.get();
closedir(dr);

return 0;
}
[\code]
One of the points I was trying to make earlier is that simply "dropping" the exe in a folder won't cause the exe to run. It's also kind of a hassle (and just plain weird) to be moving the exe around like that. Therefore I wrote the program in such a way that you should be able to drop the folder onto the exe file, which should cause it to run and open that folder. But it needs the argc, argv stuff to do that, since that's where the directory name will come from.

I have no idea how you are making the exe run by simply "dropping" it into a folder. If you mean moving it to the folder and then running it, that's kind of a strange way to do it compared to the other way. But it's up to you.
My apologies for my lack of correct terminology. Yes I meant run the exe by moving it into the folder and clicking it.
Do you have any suggestions on how I can now parse through the .csv files? For instance, I created a simple .csv and I want to make sure the 1st column second row contains the name "John"?

Thank you in advanced.

read a line,
read another line
check this second line to see if the first 5 letters a "John," //the comma ensures exact matching.
you may want to do a to-lower or to-upper before comparing if you don't care about the case

but your example was exceedingly easy. More complex ones will need to count commas to find the right column.

you need to guard against an empty file, or 1 row file, etc, so you don't look for what is not possible to exist.

you are heading down a path that implies you will want to run regex on the files, IMHO. If you are looking for a pattern, and not exact text, you will need this. That is a little more involved, of course, but its doable. Everything you have said so far could have been done with grep without batting an eye, and you can get grep on windows. Depends on whether you want to do this to learn it or just want to get it done.


I understand the logic of read a line, read another line. However, I am not sure on how to actually do this in C++. Should I import all the data into an array perhaps?

Also this will be exact text matching. The reason I cannot use grep is because the tool needs to be simple and easy enough for anyone to use.
ah! looks like this:

ifstream ifs;
string line;
ifs.open(filename);
getline(ifs,line);

etc.
I usually prefer to read the whole array into one giant string variable and manually dig around in that, but I am weird. What you asked for so far begs a line by line approach, so this is a solid approach. Pulling the whole thing in isnt useful unless you have a much more complex thing to seek in the data.

----------
Also this will be exact text matching. The reason I cannot use grep is because the tool needs to be simple and easy enough for anyone to use.
----------
Grep is a little nerdy, sure, but a shellscript/batch file wrapper around it can abstract the uglies so that anyone that can type input into a prompt can manage it. /shrug its your project, do it as you will, but you are reinventing the wheel a bit.

Last edited on
and using that imports all the data into the variable string line correct? :)

And i agree it is a bit reinventing the wheel but I dont have much choice in the matter haha.
Running the following code doesnt output all the data at once. I actually have to continuly hit enter

1
2
3
4
5
6
7
ifstream fin(name); //bring in file
			string line;
			while (getline(fin, line)) //loop until end of file
			{
				cout << '\t' << line << '\n';
				cin.get();
			}
of course you do:

cin.get(); <---- waits for user to type enter remove it if you want spam

also remember that > lets you write a file from the output, eg

c:\> myprogram > a.txt

a.txt will have your program's output in a handy text file.
will edit my post but my newest update is below.
I am storing each row of the CSV in a string.
I.E: row1 outputs: John, More, 33, 80
How can i search through this string and do a if (33 <50) output "error". if 80 >50 output "no error. "Basically, each piece of data in the string is going to be compared to some tests.
Thanks.

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
50
51
52
53
54
55
56
57
#include <stdio.h>
#include <dirent.h>
#include <iostream>
#include <string>
#include <fstream>


using namespace std;

int main(void)
{
	string row1;
	string row2;
	string row3;
	string row4;
	// Pointer for directory entry
	struct dirent *de;

	// opendir() returns a pointer of DIR type. 
	DIR *dr = opendir(".");

	// opendir returns NULL if couldn't open directory
	if (dr == NULL)
	{
		cout << "Could not open current directory" << endl;
		cin.get();
		return 0;
	}

	while ((de = readdir(dr)) != NULL)
	{
		string name(de->d_name);

		// Search directory for all files ending in .csv
		if (name.size() > 4 && name.substr(name.size() - 4) == ".csv")
		{
			cout << name << ":\n";
			ifstream fin(name); //bring in file
			string line;
			getline(fin, row1);
			 
			getline(fin, row2);
			getline(fin, row3);
			getline(fin, row4);
			cout << row1 << endl;
			cout << row2 << endl;
			cout << row3 << endl;
			cout << row4 << endl;

		}

	}
	cin.get();
	closedir(dr);

	return 0;
}
Last edited on
find comma, find comma, read next thing as integer, skip comma, read next thing as integer, do tests.

or, if you read it into a struct as columns, compare the 2 relevant columns, but its unclear if all your files are the same format given you search for the files and try to process everything no matter what you found.


you may need to do a type-test (read as string, read as string, read as string see if is integer, read as string see if is integer) and if the last 2 are not ints, fail out on that file and move to next file. I dunno, I am guessing at what you are really trying to do.

Last edited on
Sorry, let me try to explain what I am trying to do a little better. I am making a program where it searches the folder for all .CSV files all in the same format containing a ton of different data, string and integers included(all string and integers in each file will be different but in the same location within the various csv files). I then I have to verify that the data meets specific test cases. I do like the idea of reading it into a struct though!!
Last edited on
Could you potentially help figure out how to read it into a struct? Its a little strange since I cant specify the name of the csv files instead I have to search the folder for all files ending in .csv and use those. Thanks.
Pages: 12