Solved

I need to read all the xml files from a directory

Posted on 2009-05-15
13
259 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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
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.

743 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

13 Experts available now in Live!

Get 1:1 Help Now