Showing posts with label File Operations. Show all posts
Showing posts with label File Operations. Show all posts

Monday, 14 January 2013

Xerces: Writing out an XML file

This is the next in the Xerces series that shows writing out to the XML file. The output file will be written in the XML directory.



//Program tested on Microsoft Visual Studio 2010 - Zahid Ghadialy
//Example demonstrates creating an XML file 
//Based on example at: http://www.codeproject.com/Articles/32762/Xerces-for-C-Using-Visual-C-Part-2
//Xerces is xerces-c-3.1.1-x86-windows-vc-10.0

 
#include <iostream>
#include <string>
#include <sstream>
//Mandatory for using any feature of Xerces.
#include <xercesc/util/PlatformUtils.hpp>
//Use the Document Object Model (DOM) API
#include <xercesc/dom/DOM.hpp>
//Required for outputing a Xerces DOMDocument to a standard output stream (Also see: XMLFormatTarget)
#include <xercesc/framework/StdOutFormatTarget.hpp>
//Required for outputing a Xerces DOMDocument to the file system (Also see: XMLFormatTarget)
#include <xercesc/framework/LocalFileFormatTarget.hpp>

 
 
using namespace std;
XERCES_CPP_NAMESPACE_USE
 
void DoOutput2Stream(DOMDocument* pmyDOMDocument);
void DoOutput2File(DOMDocument* pmyDOMDocument, const wchar_t * FullFilePath );
 
int main()
{
  // Initilize Xerces.
  XMLPlatformUtils::Initialize();
 
  // Pointer to our DOMImplementation.
  DOMImplementation*    p_DOMImplementation = NULL;
  p_DOMImplementation = DOMImplementationRegistry::getDOMImplementation(XMLString::transcode("core"));
 
  // Pointer to our DOMDocument.
  DOMDocument*        p_DOMDocument = NULL;
 
  p_DOMDocument = p_DOMImplementation->createDocument(0, L"Hello_World", 0);
 
  DOMElement * p_RootElement = NULL;
  p_RootElement = p_DOMDocument->getDocumentElement();
 
  //Fill in the DOM document - different parts
  //Create a Comment node, and then append this to the root element.
  DOMComment * p_DOMComment = NULL;
  p_DOMComment = p_DOMDocument->createComment(L"Dates are formatted mm/dd/yy." 
                                            L" Don't forget XML is case-sensitive.");
  p_RootElement->appendChild(p_DOMComment);
 
  //Create an Element node, then fill in some attributes, and then append this to the root element.
  DOMElement * p_DataElement = NULL;
  p_DataElement = p_DOMDocument->createElement(L"data");
 
  //Copy the current system date to a buffer, then set/create the attribute.
  wchar_t wcharBuffer[128];
  _wstrdate_s(wcharBuffer, 9);
  p_DataElement->setAttribute(L"date", wcharBuffer);
 
  //Convert an integer to a string, then set/create the attribute.
  _itow_s(65536, wcharBuffer, 128, 10);
  p_DataElement->setAttribute(L"integer", wcharBuffer);
 
  //Convert a floating-point number to a wstring, then set/create the attribute.
  std::wstringstream    myStream;
  myStream.precision(8);
  myStream.setf(std::ios_base::fixed, std::ios_base::floatfield);
  myStream << 3.1415926535897932384626433832795;
  const std::wstring ws(myStream.str());
  p_DataElement->setAttribute(L"float", ws.c_str());
  p_RootElement->appendChild(p_DataElement);
 
  // Create an Element node, then fill in some attributes, add some text,
  // then append this to the 'pDataElement' element.
  DOMElement * p_Row = NULL;
  p_Row = p_DOMDocument->createElement(L"row");
 
  // Create some sample data.
  _itow_s(1, wcharBuffer, 128, 10);
  p_Row->setAttribute(L"index", wcharBuffer);
 
  /*
  Create a text node and append this as well. Some people 
  prefer to place their data in the text node
  which is perfectly valid, others prefer to use 
  the attributes. A combination of the two is quite common.
  */
  DOMText* p_TextNode = NULL;
  p_TextNode = p_DOMDocument->createTextNode(L"Comments and" 
              L" data can also go in text nodes.");
  p_Row->appendChild(p_TextNode);
 
  p_DataElement->appendChild(p_Row);
 
 
  // Create another row (this time putting data and descriptions into different places).
  p_Row = p_DOMDocument->createElement(L"row");
  p_Row->setAttribute(L"description", L"The value of PI");
  p_TextNode = p_DOMDocument->createTextNode(L"3.1415926535897932384626433832795");
  p_Row->appendChild(p_TextNode);
  p_DataElement->appendChild(p_Row);
 
  // Create another row.
  p_Row = p_DOMDocument->createElement(L"row");
  p_Row->setAttribute(L"website", L"http://www.3g4g.co.uk/");
  p_TextNode = p_DOMDocument->createTextNode(L"3G and 4G Wireless Resources");
  p_Row->appendChild(p_TextNode);
  p_DataElement->appendChild(p_Row);
 
  //Output on console
  DoOutput2Stream(p_DOMDocument);
 
  //Output to a file
  DoOutput2File(p_DOMDocument, XMLString::transcode("..\\..\\XML\\Test.xml"));
 
  // Cleanup.
  p_DOMDocument->release();
  XMLPlatformUtils::Terminate();
 
  return 0;
}
 
 
void DoOutput2Stream(DOMDocument* pmyDOMDocument)
{
  DOMImplementation    *pImplement    = NULL;
  DOMLSSerializer      *pSerializer   = NULL;
  XMLFormatTarget      *pTarget       = NULL;
 
  /*
  Return the first registered implementation that has
  the desired features. In this case, we are after
  a DOM implementation that has the LS feature... or Load/Save.
  */
  pImplement = DOMImplementationRegistry::getDOMImplementation(L"LS");
 
  /*
  From the DOMImplementation, create a DOMWriter.
  DOMWriters are used to serialize a DOM tree [back] into an XML document.
  */
  pSerializer = ((DOMImplementationLS*)pImplement)->createLSSerializer();
 
  /*
  This line is optional. It just sets a feature
  of the Serializer to make the output
  more human-readable by inserting line-feeds and tabs, 
  without actually inserting any new nodes
  into the DOM tree. (There are many different features to set.) 
  Comment it out and see the difference.
  */
 
  //The end-of-line sequence of characters to be used in the XML being written out. 
  pSerializer->setNewLine(XMLString::transcode("\n"));
 
  DOMConfiguration* pDomConfiguration = pSerializer->getDomConfig();
  pDomConfiguration->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true);
 
 
  /*
  Choose a location for the serialized output. The 3 options are:
      1) StdOutFormatTarget     (std output stream -  good for debugging)
      2) MemBufFormatTarget     (to Memory)
      3) LocalFileFormatTarget  (save to file)
      (Note: You'll need a different header file for each one)
  */
  pTarget = new StdOutFormatTarget();
  DOMLSOutput* pDomLsOutput = ((DOMImplementationLS*)pImplement)->createLSOutput();
  pDomLsOutput->setByteStream(pTarget);
  
  // Write the serialized output to the target.
  pSerializer->write(pmyDOMDocument, pDomLsOutput);
}
 
void DoOutput2File(DOMDocument* pmyDOMDocument, const wchar_t * FullFilePath )
{
 
  DOMImplementation    *pImplement     = NULL;
  DOMLSSerializer      *pSerializer    = NULL;
  XMLFormatTarget      *pTarget        = NULL;
 
  /*
  Return the first registered implementation that 
  has the desired features. In this case, we are after
  a DOM implementation that has the LS feature... or Load/Save.
  */
  pImplement = DOMImplementationRegistry::getDOMImplementation(L"LS");
 
  /*
  From the DOMImplementation, create a DOMWriter.
  DOMWriters are used to serialize a DOM tree [back] into an XML document.
  */
  pSerializer = ((DOMImplementationLS*)pImplement)->createLSSerializer();
 
 
  /*
  This line is optional. It just sets a feature 
  of the Serializer to make the output
  more human-readable by inserting line-feeds, 
  without actually inserting any new elements/nodes
  into the DOM tree. (There are many different features to set.) 
  Comment it out and see the difference.
  */
  DOMConfiguration* pDomConfiguration = pSerializer->getDomConfig();
  pDomConfiguration->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true);
 
 
  /*
  Choose a location for the serialized output. The 3 options are:
      1) StdOutFormatTarget     (std output stream -  good for debugging)
      2) MemBufFormatTarget     (to Memory)
      3) LocalFileFormatTarget  (save to file)
      (Note: You'll need a different header file for each one)
      Don't forget to escape file-paths with a backslash character, or
      just specify a file to be saved in the exe directory.
        
        eg. c:\\example\\subfolder\\pfile.xml
 
  */
  pTarget = new LocalFileFormatTarget(FullFilePath);
  // Write the serialized output to the target.
  DOMLSOutput* pDomLsOutput = ((DOMImplementationLS*)pImplement)->createLSOutput();
  pDomLsOutput->setByteStream(pTarget);
 
  pSerializer->write(pmyDOMDocument, pDomLsOutput);
}


The output is as follows:


The XML file is as follows:

Sunday, 14 October 2012

Xerces: Reading an XML file and printing it out

As I mentioned in the Xerces introductory post, here is the first program:

I have created an XML file called books.xml located in the XML directory.

All the operations will be done in the DomReader class.

main.cpp

//Program tested on Microsoft Visual Studio 2010 - Zahid Ghadialy
//Example demonstrates reading an XML file and printing it out

 
#include <iostream>
#include <xercesc/dom/DOM.hpp>
#include "DomReader.h"

using namespace std;
 
 
int main()
{
  string xmlFileName="..\\..\\XML\\books.xml";
  
  DomReader myDomReader;
 
  try
  {
    myDomReader.readDomFile(xmlFileName);
  }
  catch (runtime_error e)
  {
    cout << e.what() <<endl;
  }
  catch(...)
  {
    cout << "Unexpected error occurred" << endl;
  }
 
  return 0;
}


DomReader.h

#include <string>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>

using namespace std;
XERCES_CPP_NAMESPACE_USE
 
class DomReader
{
public:
  DomReader();
  ~DomReader();
 
  void readDomFile(std::string&) throw(std::runtime_error);
  
 
private:
  void convertDomToXmlString(DOMNode* domNode, std::string &) throw(std::runtime_error);
  string narrow( const wstring& str );
  xercesc::XercesDOMParser *domFileParser;
 
};


DomReader.cpp

#include <iostream>
#include <sstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
 
#include "DomReader.h"

 
DomReader::DomReader()
{
  XMLPlatformUtils::Initialize();
  domFileParser = new XercesDOMParser;
  domFileParser->setValidationScheme(XercesDOMParser::Val_Never);
  domFileParser->setDoNamespaces(false);    // optional
}
 
DomReader::~DomReader()
{
  if(domFileParser)
    delete domFileParser;
  XMLPlatformUtils::Terminate();
}
 
void DomReader::readDomFile(string& domFileName) throw(std::runtime_error)
{
  //Check if filename / file is good
  struct _stat fileStatus;
 
  int returnStat = _stat(domFileName.c_str(), &fileStatus);
  if ( returnStat == ENOENT )
    throw ( runtime_error("Path file_name does not exist, or path is an empty string.") );
  else if ( returnStat == ENOTDIR )
    throw ( std::runtime_error("A component of the path is not a directory."));
  else if( returnStat == ELOOP )
    throw ( std::runtime_error("Too many symbolic links encountered while traversing the path."));
  else if( returnStat == EACCES )
    throw ( std::runtime_error("Permission denied."));
  else if( returnStat == ENAMETOOLONG )
    throw ( std::runtime_error("File can not be read\n"));
  else if( returnStat == -1)
    throw ( std::runtime_error("Other Unknown Error\n"));
 
  //Parse the file
  domFileParser->parse(domFileName.c_str());
 
  //No need to free this pointer - owned by the parent parser object
  DOMDocument* xmlDoc = domFileParser->getDocument();
  if( !xmlDoc ) throw(std::runtime_error( "DOM document could not be opened" ));
 
  //Get the top-level element: Name is "root". No attributes for "root"
  DOMElement* elementRoot = xmlDoc->getDocumentElement();
  if( !elementRoot ) throw(std::runtime_error( "empty XML document" ));
 
  string xmlString;
  try
  {
    convertDomToXmlString(elementRoot, xmlString);
  }
  catch(runtime_error e)
  {
    throw(runtime_error(e));
  }
  cout << "DOM File: "<< domFileName << " output is as follows "<<endl;
  cout << xmlString;
  cout << endl;
}
 
void DomReader::convertDomToXmlString(DOMNode* domNode, string &xmlString) throw(std::runtime_error)
{
  try
  {
    DOMImplementation *domImpl = DOMImplementationRegistry::getDOMImplementation(L"LS");
    DOMLSSerializer   *domSerializer = ((DOMImplementationLS*)domImpl)->createLSSerializer();
    XMLCh *xmlBuffer = domSerializer->writeToString(domNode);
    xmlString = narrow(xmlBuffer);
    XMLString::release (&xmlBuffer);
    delete domSerializer;
  }
  catch(XMLException& e)
  {
    char *xmlErrMessage = XMLString::transcode(e.getMessage());
    throw runtime_error(xmlErrMessage);
  }
  catch(...)
  {
    throw runtime_error("Unknown error in convertDomToXmlString\n");
  }
}
 
string DomReader::narrow( const wstring& str )
{
  ostringstream stm ;    
  const ctype<char>& ctfacet = use_facet< ctype<char> >( stm.getloc() ) ;    
  for( size_t i=0 ; i<str.size() ; ++i )
    stm << ctfacet.narrow( str[i], 0 ) ;    
  return stm.str() ;
}


The output is as follows:



Tuesday, 29 March 2011

Reading file names from directory

The other day I had to read all the file names from a directory and I found it really difficult to write a simple program to do that. While searching I ended up at Stack Overflow and the following example is taken from here.

Note that the 'dirent.h' is not available as standard windows file and the best option is to download it from here and add it in your include directory of the project.

The program as follows:


//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
#include<iostream>

#pragma warning( disable : 4996 )
#include "dirent.h"
#pragma warning( default : 4996 )

using namespace
std;

int
main(int argc, char *argv[])
{

if
(argc != 2)
{

cout<<"Usage: "<<argv[0]<<" <Directory name>"<<endl;
return
-1;
}


DIR *dir;
dir = opendir (argv[1]);
if
(dir != NULL)
{

cout<<"Directory Listing for "<<argv[1]<<" : "<<endl;
struct
dirent *ent;
while
((ent = readdir (dir)) != NULL)
{

cout<<ent->d_name<<endl;
}
}

else

{

cout<<"Invalid Directory name"<<endl;
return
-1;
}


return
0;
}

Note that in this program we put Command-line arguments argc and argv. What this means is that the final .exe is run using command prompt and the first parameter will be exe file name and the second parameter will be the directory path or you can add the directory path in Debugging->Command arguments of the properties

You may also encounter the following warning

warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

to get rid of it, I have used the #Pragma supressor.

You may also get the following error:

error C2664: 'FindFirstFileW' : cannot convert parameter 1 from 'char *' to 'LPCWSTR'
to get rid of it, go to properties->general->Character set - default is 'Use Unicode Charachter set', change it to 'Use Multi-Byte Character Set'

The output is as follows:

Tuesday, 22 March 2011

Reading Files into Vector

Thought of this while trying to create a parser. The intention is to read a complete text file into a vector and then use this vector for other operations. This program shows how to read from a text file into vectors.

The input file is as follows:

Line num 1

Another line

Line number 3

4th Line!

**%** Last line **%**

Program as follows:



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
#include <iostream>
#include <vector>
#include <fstream>
#include <string>

using namespace
std;

int
main()
{

vector<std::string> lines;
lines.reserve(5000); //Assuming that the file to read can have max 5K lines

string fileName("test.txt");

ifstream file;
file.open(fileName.c_str());

if
(!file.is_open())
{

cerr<<"Error opening file : "<<fileName.c_str()<<endl;
return
-1;
}


//Read the lines and store it in the vector
string line;
while
(getline(file,line))
{

lines.push_back(line);
}


file.close();

//Dump all the lines in output
for(unsigned int i = 0; i < lines.size(); i++)
{

cout<<i<<". "<<lines[i]<<endl;
}


return
0;
}




Output as follows:

Wednesday, 25 November 2009

Input/Output with files

The following is a simple program to show reading, writing and appending to files. You can read more about this feature at cplusplus.com.




//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
#include <iostream>
#include <fstream>
#include <string>

using namespace
std;

int
main()
{

string line;
cout<<"\nFile 1 operations - Writing to Hello.txt"<<endl;
ofstream file1; //OUTPUT file Stream
file1.open("Hello.txt"); //Open the file
file1 << "Writing something something to a file"<<endl;
file1 << "This is enough for the time being"<<endl;

if
(file1.is_open()) //Check if open
{
/*
while (!file1.eof())
{
getline (file1,line); - NOT POSSIBLE because of ofstream
cout << line << endl;
}
*/

}

file1.close(); //Close file1

cout<<"\nFile 2 operations - Reading from Hello.txt"<<endl;
ifstream file2; //INPUT file stream
file2.open("Hello.txt"); //Open the file
if(file2.is_open()) //Check if open
{
while
(!file2.eof())
{

getline (file2,line);
cout << line << endl;
}
}

file2.close(); //Close file2


cout<<"\nFile 3 operations - Appending and Reading from Hello.txt"<<endl;
fstream file3; //INPUT file stream
file3.open("Hello.txt", ios::in | ios::out); //Open the file
if(file3.is_open()) //Check if open
{
//We want to put a new line at the end of the file
file3.seekp(0, ios::end);
file3 << "This is new line added file 3"<<endl;
//Now reset the file pointer to the start of the file
file3.seekg(0, ios::beg);
while
(!file3.eof())
{

getline (file3,line);
cout << line << endl;
}
}

file3.close(); //Close file3

return
0;
}








The output is as follows: