how to open subfolder with fstream in c++ - c++

hello I want to read a file located in a subfolder of my program.I succeeded to read the file in the mainfolder of my program.But i cant read the file in a subfolder.
I tried to add a new string named subdir = "/*/" and do like this to get the subfolder but the program refused to take the new paths with my string subdir.Does anyone has a clue on how to do it ? I am running out of ideas lool.
char resulta[ MAX_PATH];
DWORD flicksa = GetModuleFileName(NULL,resulta,MAX_PATH);
_chdir(std::string(resulta,GetCurrentDirectory(flicksa,resulta)).c_str());
std::string path = "/Users/Aymann/Desktop/arraysort/2CPP-REVISIONS/Supcount/";
std::string searchPattern = "/*.cpp";
std::string fullSearchPath = path + searchPattern;
WIN32_FIND_DATA FindData;
HANDLE hFind;
hFind = FindFirstFile( fullSearchPath.c_str(), &FindData );
if( hFind == INVALID_HANDLE_VALUE )
{
cout << "Error searching directory\n";
return -1;
}
do
{
char c;
string filePath = path + FindData.cFileName;
ifstream in( filePath.c_str() );
if( in.is_open() )
{in.get(c);
while (in) {
while (in && c != '\n') {
in.get(c);
}
_rowcount = _rowcount + 1;
in.get(c);
} // do stuff with the file here
}
else
{
cout << "Problem opening file " << FindData.cFileName << "\n";
}
}
while( FindNextFile(hFind, &FindData) > 0 );
if( GetLastError() != ERROR_NO_MORE_FILES )
{
cout << "Something went wrong during searching\n";
}

You cannot pass wildcards to fstream.
Solution: descent folders, open files.
See glob(), opendir(), readdir(), closedir().

Related

Drive Search does not locate .docx and .txt files

void findFile(const std::wstring &directory, wstring inputSearch)
{ // , char *currDrives){ //function for algorithm to search your computer to find what you want to load
//wcout << directory << endl;
//cout << "In" << endl;
wstring search = inputSearch;
std::wstring tmp = directory + L"\\*";
size_t found;
WIN32_FIND_DATAW file;
HANDLE search_handle = FindFirstFileW(tmp.c_str(), &file);
if (search_handle != INVALID_HANDLE_VALUE)
{
std::vector<std::wstring> directories;
do
{
found = tmp.find_last_of(L"/\\");
if (tmp.substr(found + 1) == inputSearch) {
cout << "Found File" << endl;
continueSearching = false;
foundFilePath = tmp;
}
if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if ((!lstrcmpW(file.cFileName, L".")) || (!lstrcmpW(file.cFileName, L".."))) {
continue;
}
}
tmp = directory + L"\\" + std::wstring(file.cFileName);
bruteForceComp++;
//std::wcout << tmp << std::endl;
if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
directories.push_back(tmp);
} while (FindNextFileW(search_handle, &file) && continueSearching == true);
FindClose(search_handle);
for (std::vector<std::wstring>::iterator iter = directories.begin(), end = directories.end(); iter != end; ++iter) {
findFile(*iter, inputSearch);
}
}
}
We have this function that searches all sub-directories within a certain drive. We compare this to a search term that is inputted by the user. (The drive and the search term are the two parameters passed into the function) We locate .exe files fine and a bunch of other files, but when we try to locate a .docx or .txt file they do not appear. Any help with finding why would be appreciated. We're somewhat stumped.
Thanks!
foundFilePath is a static wstring by the way. It is where we store the matching path to the search term. Search term is inputted as word.exe or yay.docx also.

How to read specific file names of a directory into an array

I tried to read all file names of a directory into array and my code successfully addes whole file names into array. However, what i need it to do,
1st one is getting ,not all of them, only spesific file names which end like .cpp or .java. It should be done in this part and my comparisons did not work. How can i do that ?
DIR *dir;
struct dirent *dirEntry;
vector<string> dirlist;
while ((dirEntry = readdir(dir)) != NULL)
{
//here
dirlist.push_back(dirEntry->d_name);
}
2dn one is getting the directory location from user. I couldn't do that also, it only works if i write the location adress, how can i get location from user to get files ?
dir = opendir(//here);
I think this would work for your case,
DIR* dirFile = opendir( path );
if ( dirFile )
{
struct dirent* hFile;
errno = 0;
while (( hFile = readdir( dirFile )) != NULL )
{
if ( !strcmp( hFile->d_name, "." )) continue;
if ( !strcmp( hFile->d_name, ".." )) continue;
// in linux hidden files all start with '.'
if ( gIgnoreHidden && ( hFile->d_name[0] == '.' )) continue;
// dirFile.name is the name of the file. Do whatever string comparison
// you want here. Something like:
if ( strstr( hFile->d_name, ".txt" ))
printf( "found an .txt file: %s", hFile->d_name );
}
closedir( dirFile );
}
Ref: How to get list of files with a specific extension in a given folder
#include <iostream>
#include "boost/filesystem.hpp"
using namespace std;
using namespace boost::filesystem;
int main(int argc, char *argv[])
{
path p (argv[1]);
directory_iterator end_itr;
std::vector<std::string> fileNames;
std::vector<std::string> dirNames;
for (directory_iterator itr(p); itr != end_itr; ++itr)
{
if (is_regular_file(itr->path()))
{
string file = itr->path().string();
cout << "file = " << file << endl;
fileNames.push_back(file);
}
else if (is_directory(itr->path()))
{
string dir = itr->path().string();
cout << "directory = " << dir << endl;
dirNames.push_back(dir);
}
}
}

Concat command line arguments for FindFirstFile parameter in C++ VS 2010 OpenCV

Has anyone used the FindFirstFile function to scan multiple files of the same type?
int main(int argc, char** argv){
if(argc != 3)
{
cout <<" Usage: Run [dir of images folder] [file format]" << endl;
cout <<" Example: Run \\imgs\\\\ .jpg " << endl;
return 0;
}
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
string dir = argv[1]; // store user input dir
string type = argv[2]; // store user input file type
stringstream sst;
sst << dir << "*" << type;
string folderDir = sst.str();
sst.str("");
cout << "Scanning all " << type << " files in "<< dir << endl;
cout << folderDir << endl;
/* LOADING IMAGES IN FOLDER */
I tried folderDir.c_str() instead of "\imgs\*.jpg" but I can't make it work;
hFind = FindFirstFile("\imgs\\*.jpg", &FindFileData); //images must be in .vcxproj dir
if (hFind != INVALID_HANDLE_VALUE){
int i = 0;
do {
char loc[50] = "\imgs\\"; // Obvsly, I couldn't assign argv[1] here
images.push_back(imread(strcat(loc,FindFileData.cFileName))); //pushes images into vector
img_fname[i] = FindFileData.cFileName; // stores file names into string array
cout << "Successfully loaded " << FindFileData.cFileName << endl; //prints loaded file names
i++;
}while(FindNextFile(hFind, &FindFileData));
}
Also, may I ask help in assigning string dir to char loc[50] = "\imgs\\";?
If only char loc[50] = dir; is possible...
I tried strcpy(loc, dir.c_str()); after instantiating loc but it still failed. Gave me an error (Unrecognized or unsupported array type) in unknown function
i think, it should be only one backslash there:
"imgs\*.jpg" instead of "\imgs\\*.jpg".
this works fine for me ( and gives me the filelist ):
std::vector<std::string> readdir( const char * dmask )
{
std::vector<std::string> vec;
HANDLE hFind;
WIN32_FIND_DATA FindFileData;
if ((hFind = FindFirstFile(dmask, &FindFileData)) != INVALID_HANDLE_VALUE)
{
do {
vec.push_back( FindFileData.cFileName );
} while(FindNextFile(hFind, &FindFileData));
FindClose(hFind);
}
return vec;
}
std::vector<std::string> files = readdir("imgs\*.jpg");

Traversing directory and iterators in c++

I am an absolute newbie to C++ and have only started to program with it 3 days ago.
I am trying to do the folliwng:
traverse a directory for X.X files (typically .), and for each file, do the following:
Search within the file for a string (findFirst) and then search until another string (findLast) - The files will be HTML format.
In this selection, I want to perform several tasks (yet to write) - but they will be the following:
One of the strings will be the Filename I want to write to. - so extract this field and create an outputfile with this name
Some of the lines will be manufacturer part numbers - extract these and format the output file accordingly
most of it will be description of product. Again - this will be in an HTML construct - so extract this and format the output file.
So far, I have managed to get working the traverse directory, and selecting the start and finish keywords - using some help from the internet.
My problem is here
processFiles(inputFileName, "testing", "finish");
I need the inputFileName to be the name of the traversed filename.
All the examples I have found simply print the filename using cout
I need to pass this into the processFiles function.
Can someone tell me what i need to use? i have tried it->c_Str() and other variations of (*it) and .at, .begin etc
my non printing example is below:
// Chomp.cpp : Defines the entry point for the console application.
//
#include <stdafx.h>
#include <windows.h>
#include <string>
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <cctype>
#include <algorithm>
#include <vector>
#include <stack>
//std::ifstream inFile ( "c:/temp/input.txt" ) ;
std::ofstream outFile( "c:/temp/output.txt") ;
using namespace std;
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
void openFiles()
{
if (!(outFile.is_open()))
{
printf ("Could not Create Output file\n");
exit(0);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
bool ListFiles(wstring path, wstring mask, vector<wstring>& files)
{
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA ffd;
wstring spec;
stack<wstring> directories;
directories.push(path);
files.clear();
while (!directories.empty())
{
path = directories.top();
spec = path + L"\\" + mask;
directories.pop();
hFind = FindFirstFile(spec.c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE)
return false;
do
{
if (wcscmp(ffd.cFileName, L".") != 0 && wcscmp(ffd.cFileName, L"..") != 0)
{
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
directories.push(path + L"\\" + ffd.cFileName);
else
files.push_back(path + L"\\" + ffd.cFileName);
}
} while (FindNextFile(hFind, &ffd) != 0);
if (GetLastError() != ERROR_NO_MORE_FILES)
{
FindClose(hFind);
return false;
}
FindClose(hFind);
hFind = INVALID_HANDLE_VALUE;
}
return true;
}
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
void processFiles(const wchar_t *inFileName, std::string findFirst,std::string findLast )
{
/*
std::string findFirst = "testing" ;
std::string findLast = "finish" ;
*/
std::string inputLine ;
int lineNum = 0 ;
char buffer[2048];
size_t found = 0;
std::ifstream inFile;
inFile.open (inFileName); // Open The file
if (inFile.is_open())
{
while( std::getline( inFile, inputLine ))
{
++lineNum ;
// printf ("Line len = %d\n ", inputLine.length());
if( (found = inputLine.find(findFirst)) != std::string::npos )
{
std::cout << "###Line " << lineNum << " At Position [ " << found << " ]\n" ;
sprintf_s(buffer, 2048, "[%-5.5d] %s\n", lineNum, inputLine.c_str());
outFile << buffer ;
bool foundLast = 0;
while( std::getline( inFile, inputLine ))
{
++lineNum ;
sprintf_s(buffer, 2048, "[%-5.5d] %s\n", lineNum, inputLine.c_str());
if( (found = inputLine.find(findLast)) != std::string::npos )
{
outFile << buffer ;
break; // Found last string - so stop after printing last line
}
else
outFile << buffer ;
}
}
else
{
// std::cout << "=>" << inputLine << '\n' ;
}
}
}
else
{
printf ("Cant open file \n");
exit(0);
}
inFile.close() ; // Close The file
}
/////////////////////////////////////////////////////////////////////////////////////////////
/// M A I N
/////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
std::ifstream inFile ;
int startLine = 0;
int endLine = 0;
int lineSize = 0;
char buffer[512];
vector<wstring> files; // For Parsing Directory structure
openFiles();
// Start The Recursive parsing of Directory Structure
if (ListFiles(L"C:\\temp", L"*.*", files))
{
for (vector<wstring>::iterator it = files.begin(); it != files.end(); ++it)
{
printf ("Filename1 is %s\n", it->c_str());
printf ("Filename2 is %s\n", files.begin());
outFile << "\n------------------------------\n";
//outFile << it << endl;
wcout << it->c_str() << endl;
outFile << "\n------------------------------\n";
const wchar_t *inputFileName = it->c_str();
// processFiles(inputFileName, "testing", "finish");
// getchar();
}
}
outFile.close();
getchar();
}
Make your processFile accept a wstring, viz:
void processFiles(wstring inFileName, std::string findFirst,std::string findLast )
{
// Make the necessary changes so that you use a wstring for inFileName
}
Call it from main() using:
processFiles(*it, "testing", "finish");
You need to change processFile to use a wifstream instead of a ifstream and you should change all of your narrow strings to use wide strings (or vice versa). Narrow strings and wide strings are not compatible with each other and in order to use one with the other a conversion function must be used such as mbstowcs.
Edit:
You can find an example that should compile here.

C++ Looping Through Files In Directory and Writing to a Different Directory

I am attempting to modify some existing C++ code to work with my needs, but having never used C++ before, I am having some difficulties.
My goal is:
--> time and memory-intensive processes for preparation
for each file in directory:
open file;
generate a tagged representation; //the current code just does this
write file; //different directory but same filename
The reason I do not want to just call the C++ program for each file (with, for instance, a shell script) is that prior to the below code running, time and memory-intensive pre-processing steps are performed. (These take about 45-60sec. while the code only takes about 2-5sec. to run.)
I have pasted the section of the code below. I want to read the arguments from the command line.
int main(int argc, char** argv) {
/*
pre-processing stuff
*/
/* for each file */
HANDLE hFind = INVALID_HANDLE_VALUE;
string path = argv[1];
string outpath = argv[2];
WIN32_FIND_DATA ffd;
//EDIT 2:
cout << "Path: " << path << '\n';
cout << "Outpath: " << outpath << '\n';
hFind = FindFirstFile(path.c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE) {
cout << "error searching directory\n";
return false;
}
do {
//istream *is(&std::cin);
string filePath = path + ffd.cFileName;
ifstream in( filePath.c_str() );
if (in) {
/* for each line */
string line;
int n = 1;
string str;
string fullOutpath = outpath + ffd.cFileName;
ofstream File;
File.open(fullOutpath);
while (getline(in, line)) {
if (line.size() > 1024) {
cerr << "warning: the sentence seems to be too long at line " << n;
cerr << " (please note that the input should be one-sentence-per-line)." << endl;
}
string postagged = bidir_postag(line, vme, vme_chunking, dont_tokenize);
/* output to file */
File << postagged << endl;
//cout << postagged << endl;
/* increment counter */
n++;
}
File.close();
} else {
cout << "Problem opening file " << ffd.cFileName << "\n";
}
} while (FindNextFile(hFind, &ffd) != 0);
if (GetLastError() != ERROR_NO_MORE_FILES) {
cout << "Something went wrong during searching\n";
}
return true;
}
Currently, I am getting a compiler error: EDIT: compiler error fixed, thanks Blood!, but see below...
error: no matching function for call to 'std::basic_ofstream<char>::open<std::string&>
Any thoughts? Please let me know if you need more code/information. Also, I should add that I'm running these on Windows XP using command prompt.
Thanks.
EDIT:
It now compiles (thanks Blood), though when it runs it is only attempting to open the directory, not the files in the directory.
Problem opening file directory_name.
The ifstream should be opening the files in teh directory, not the directory itself.
EDIT 2:
I am running the executable fromt he command line with the following prompt:
.\tag.exe C:\indir C:\outdir
I have also tried:
.\tag.exe C:\indir\* C:\outdir\
This enumerates all the files, but how can I capture them? Also, is there a simpler way to modify my code/input?
I have also tried:
.\tag.exe C:\indir\ C:\outdir\
This gives: error searching directory.
EDIT 3:
Using:
.\tag.exe "C:\indir\*" C:\outdir\
I get the output:
Problem opening file .
Problem opening file ..
Problem opening file 2967
Problem opening file 2966
Problem opening file 4707
etc. (100s)
Solution:
Here are the key changes to the code (thanks Nate Kohl!):
string path = argv[1];
path += "\\*";
hFind = FindFirstFile(path.c_str(),&ffd);
// in the 'do-while' loop
string filePath = argv[1];
filePath += "\\";
filePath += ffd.cFileName;
ifstream in(filePath.c_str());
//regarding the outpath
fullOutpath = outpath + "\\";
fullOutpath += ffd.cFileName;
File.open(fullOutpath.c_str());
and from the command line:
.\tag.exe C:\indir C:\outdir
The help was very much appreciated.
Make sure you're passing the right path format to FindFirstFile.
From the documentation:
To examine a directory that is not a root directory, use the path to
that directory, without a trailing backslash. For example, an argument
of "C:\Windows" returns information about the directory "C:\Windows",
not about a directory or file in "C:\Windows". To examine the files
and directories in "C:\Windows", use an lpFileName of "C:\Windows\*".
Edit:
I'm not near a windows box right now (so this may not compile!) but I imagine that "loop over each file in a directory" would look something like this:
// argv[1] is the input path with no trailing characters, e.g. "c:\indir"
// add a wildcard because FindFirstFile expects e.g. "c:\indir\*"
TCHAR wildcard_path[MAX_PATH];
PathCombine(wildcard_path, argv[1], "*");
// iterate over each file
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile(wildcard_path, &ffd);
if (hFind == INVALID_HANDLE_VALUE) { } // error
do {
// ignore directories
if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
// create a full path for each file we find, e.g. "c:\indir\foo.txt"
TCHAR file_path[MAX_PATH];
PathCombine(file_path, argv[1], ffd.cFileName);
// ...and do something with file_path.
}
} while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);