Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

I need to read all the xml files from a directory

Posted on 2009-05-15
13
Medium Priority
?
269 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Technology Partners: 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 2000 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

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

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

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
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.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

670 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