Solved

I need to read all the xml files from a directory

Posted on 2009-05-15
13
263 Views
Last Modified: 2012-06-21
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
0
Comment
Question by:stanisla
  • 7
  • 6
13 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 24398853
If you want that to be cross-platform, Boost would indeed be the way to go, e.g. (code taken from http://www.daniweb.com/forums/thread74944.html#)
#include <iostream>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/fstream.hpp>
using namespace boost::filesystem; 
using namespace std;
 
void show_files( const path & directory, bool recurse_into_subdirs = true )
{
  if( exists( directory ) )
  {
    directory_iterator end ;
    for( directory_iterator iter(directory) ; iter != end ; ++iter )
      if ( is_directory( *iter ) )
      {
        cout << iter->native_directory_string() << " (directory)\n" ;
        if( recurse_into_subdirs ) show_files(*iter) ;
      }
      else 
        cout << iter->native_file_string() << " (file)\n" ;
  }
}

Open in new window

0
 
LVL 86

Expert Comment

by:jkr
ID: 24398862
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);
}

Open in new window

0
 
LVL 86

Expert Comment

by:jkr
ID: 24398875
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);
  }
}

Open in new window

0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:stanisla
ID: 24399149
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_traits<char>,std::allocator<char> >

Any ideas?
0
 
LVL 86

Expert Comment

by:jkr
ID: 24399170
You heed to double the backslash, since it is an escaope character in C++, i.e.
show_files( "C:\\testxmls" ) ;

Open in new window

0
 

Author Comment

by:stanisla
ID: 24399206
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_string() << " (file)\n" ;
      }
}
catch(exception & exp)
{
      string errDesc = exp.what();
      cout << errDesc << endl;
}
0
 
LVL 86

Expert Comment

by:jkr
ID: 24399231
Hm, stupid question: Does that directory exist and is the name exactly like that (no uppercase letters etc.)?
0
 

Author Comment

by:stanisla
ID: 24399262
yes, I just confirmed that it's there
0
 

Author Comment

by:stanisla
ID: 24399270
and the name is exact
0
 
LVL 86

Expert Comment

by:jkr
ID: 24399295
Hm, does

inputXMLPath = "C:/testxmls";

work?
0
 

Author Comment

by:stanisla
ID: 24399420
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_traits<char>,std::allocator<char> >
0
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
ID: 24399478
OK, what about
path inputXMLPath("C:\\testxmls", native); // <----!
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_string() << " (file)\n" ;
      }
}
catch(exception & exp)
{
      string errDesc = exp.what();
      cout << errDesc << endl;
}

Open in new window

0
 

Author Comment

by:stanisla
ID: 24399789
That did it. Thanks
0

Featured Post

Secure Your Active Directory - April 20, 2017

Active Directory plays a critical role in your company’s IT infrastructure and keeping it secure in today’s hacker-infested world is a must.
Microsoft published 300+ pages of guidance, but who has the time, money, and resources to implement? Register now to find an easier way.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

713 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question