stanisla
asked on
I need to read all the xml files from a directory
I have a directory c:\testxmls and in there I have many xmls files. I don't know the full names of xmls ahead of time. Using C++ that runs on both windows and linux I need to write code that will read each xml in the directory and save the name in a vector. Can you please provide me with full code that will do this. We also have boost version 1_33_1 so feel free to provide boost code if it's not possible with regular C++.
Thanks in advance
Thanks in advance
BTW, a pure Windows solution would be that hre: http://msdn.microsoft.com/en-us/library/aa365200.aspx ("Listing the Files in a Directory"):
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
void ErrorHandler(LPTSTR lpszFunction);
int _tmain(int argc, TCHAR *argv[])
{
WIN32_FIND_DATA ffd;
LARGE_INTEGER filesize;
TCHAR szDir[MAX_PATH];
size_t length_of_arg;
HANDLE hFind = INVALID_HANDLE_VALUE;
DWORD dwError=0;
// If the directory is not specified as a command-line argument,
// print usage.
if(argc != 2)
{
_tprintf(TEXT("\nUsage: %s <directory name>\n"), argv[0]);
return (-1);
}
// Check that the input path plus 2 is not longer than MAX_PATH.
StringCchLength(argv[1], MAX_PATH, &length_of_arg);
if (length_of_arg > (MAX_PATH - 2))
{
_tprintf(TEXT("\nDirectory path is too long.\n"));
return (-1);
}
_tprintf(TEXT("\nTarget directory is %s\n\n"), argv[1]);
// Prepare string for use with FindFile functions. First, copy the
// string to a buffer, then append '\*' to the directory name.
StringCchCopy(szDir, MAX_PATH, argv[1]);
StringCchCat(szDir, MAX_PATH, TEXT("\\*"));
// Find the first file in the directory.
hFind = FindFirstFile(szDir, &ffd);
if (INVALID_HANDLE_VALUE == hFind)
{
ErrorHandler(TEXT("FindFirstFile"));
return dwError;
}
// List all the files in the directory with some info about them.
do
{
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
_tprintf(TEXT(" %s <DIR>\n"), ffd.cFileName);
}
else
{
filesize.LowPart = ffd.nFileSizeLow;
filesize.HighPart = ffd.nFileSizeHigh;
_tprintf(TEXT(" %s %ld bytes\n"), ffd.cFileName, filesize.QuadPart);
}
}
while (FindNextFile(hFind, &ffd) != 0);
dwError = GetLastError();
if (dwError != ERROR_NO_MORE_FILES)
{
ErrorHandler(TEXT("FindFirstFile"));
}
FindClose(hFind);
return dwError;
}
void ErrorHandler(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
Oh, and for the sake of being complete, here's how yu'd do that in Linux/UN*X:
#include <sys/types.h>
#include <dirent.h>
int main(int argc, char **argv)
{
DIR *dirHandle;
struct dirent * dirEntry;
dirHandle = opendir("."); /* open current dir */
if (dirHandle) {
while (0 != (dirEntry = readdir(dirHandle))) {
puts(dirEntry->d_name);
}
closedir(dirHandle);
}
}
ASKER
jkr,
I need to use the first solution because the code needs to run on both windows and linux but I'm getting a runtime exception below on line "if( exists( directory ) )"
{"boost::filesystem::path: invalid name "C:\testxmls" in path: "C:\testxmls""} std::basic_string<char,std ::char_tra its<char>, std::alloc ator<char> >
Any ideas?
I need to use the first solution because the code needs to run on both windows and linux but I'm getting a runtime exception below on line "if( exists( directory ) )"
{"boost::filesystem::path:
Any ideas?
You heed to double the backslash, since it is an escaope character in C++, i.e.
show_files( "C:\\testxmls" ) ;
ASKER
I did initially. It throws the same exception I mentioned earlier.
Here is my code snippet.
inputXMLPath = "C:\\testxmls";
if ( exists( inputXMLPath ) )
{
directory_iterator end_iter;
for ( directory_iterator dir_itr( inputXMLPath );dir_itr != end_iter; ++dir_itr )
{
if ( is_directory( *dir_itr ) )
cout << dir_itr->native_directory_ string() << " (inputXMLPath )\n" ;
else
cout << dir_itr->native_file_strin g() << " (file)\n" ;
}
}
catch(exception & exp)
{
string errDesc = exp.what();
cout << errDesc << endl;
}
Here is my code snippet.
inputXMLPath = "C:\\testxmls";
if ( exists( inputXMLPath ) )
{
directory_iterator end_iter;
for ( directory_iterator dir_itr( inputXMLPath );dir_itr != end_iter; ++dir_itr )
{
if ( is_directory( *dir_itr ) )
cout << dir_itr->native_directory_
else
cout << dir_itr->native_file_strin
}
}
catch(exception & exp)
{
string errDesc = exp.what();
cout << errDesc << endl;
}
Hm, stupid question: Does that directory exist and is the name exactly like that (no uppercase letters etc.)?
ASKER
yes, I just confirmed that it's there
ASKER
and the name is exact
Hm, does
inputXMLPath = "C:/testxmls";
work?
inputXMLPath = "C:/testxmls";
work?
ASKER
Nope, now I'm getting the following exception
+ errDesc {"boost::filesystem::path: invalid name "C:" in path: "C:/testxmls""} std::basic_string<char,std ::char_tra its<char>, std::alloc ator<char> >
+ errDesc {"boost::filesystem::path:
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
That did it. Thanks
Open in new window