Solved

I need to read all the xml files from a directory

Posted on 2009-05-15
13
260 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
 

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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
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…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

867 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

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now