开发者

C++ IO vs Java IO

Note that this is NOT a "better-than" discussion.

I'm a Java programmer, and it makes me feel incredibly dumb not to know how to do very much C++ file IO.

I need to make very simple adapter for XML parsers, just like code below says

In Java, I could just use:

BufferedReader reader = new BufferedReader(
  new InputStreamReader(xmlInputStream));

String xml = "";
String line = null;
while ((line = reader.readLine()) != null) {
  xml += line + "\n";
}

return xmlParser11.parse(xml);

Biggest question for me is what to do with this reader in C++

Thanks very much!

开发者_JS百科

edit cutted ;)


To give a gentler introduction, the following C++ code is mimicking your Java code as much as sensible:

#include <iostream>
#include <fstream>
#include <string>
int main()
{
    std::ifstream xmlInputStream("input.xml"); // or istringstream or istream
    std::string xml;
    std::string line;
    while(getline(xmlInputStream, line))
    {
        xml += line + "\n";
    }
    //return xmlParser11.parse(xml);
    std::cout << xml << '\n';
}

But of course one doesn't have to loop to read an input stream into a string in C++: the input stream can be represented as a pair of iterators, which can be used in many different ways:

#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
int main()
{
    std::ifstream xmlInputStream("input.xml");
    std::istreambuf_iterator<char> beg(xmlInputStream), end;
    std::string xml(beg, end);
    std::cout << xml << '\n';
}

But often a temporary string object is not even needed: a C++ parser could operate on an input stream or on a pair of iterators directly.


If you are reading from a file, you could do it like this:

std::ifstream file("myfile.xml");
std::stringstream xml;

std::copy(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), 
          std::ostream_iterator<char>(xml));

This will read the entire file into the std::stringstream xml, including line-breaks and all (like in your sample-code). You can then access it as an std::string using xml.str().


This is using STL -- did you mean to ask about C++ or do you want the C equivalent (i.e. using fopen, fread etc)?

// main.cpp
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
  string line;
  string xml;
  ifstream myfile("example.txt");

  if( myfile.is_open() ) {
    while( myfile.good() ) {
      getline (myfile,line);
      xml += line + "\n";
    }
    myfile.close();
  }
  else
     cout << "Unable to open file"; 

  return 0;
}


You can do exactly the same thing in C++:

std::ifstream reader( xmlInputStream.c_str() );
if ( !reader.is_open() ) {
    //  error handling here...
}

std::string xml;
std::string line;
while ( std::getline( reader, line ) ) {
    xml += line + '\n';
}

It's probably not the best solution, but it's already fairly good. I'd probably write something like:

std::string xml(
    (std::istringstream_iterator<char>( reader )),
    (std::istringstream_iterator<char>()) );

(Note that at least one set of the extra parentheses are needed, due to an anomaly in the way C++ would parse the statement otherwise.)

Or even:

std::string
readCompleteFile( std::istream& source )
{
    return std::string(
        std::istringstream_iterator<char>( source ),
        std::istringstream_iterator<char>() );
}

(Look ma, no variables:-)!) Both of these solutions preserve the newlines in the original file, so you don't need to put them back in after reading.


Several comments on the edit:

  • It would be extremely rare to take an `std::ifstream&` as an argument, rather than an `std::istream&`. About the only time you see `std::ifstream` is when defining the object itself.
  • The error checking as to whether you've successfully opened the stream or not belongs where you opened, not in some function called with (what should be) an `std::istream&`. (You can't check whether an `std::istream` is open or not, because for many stream types, the concept of "open" doesn't exist.)
  • It's not clear what the sematncis of `XML` are: are they value, in which case it supports copy and assignment, you never allocate one dynamically, and you return by value from `XMLParser11::Parse`; or is this some sort of entity object, in which case, you return a pointer (or possibly an `std::auto_ptr`, in order to make especially sure that the client knows that he is responsible for deleting it.
  • At any case, if `XML` is allocated dynamically, you should keep it in an `std::auto_ptr` in `XMLParser11::Parse`, to ensure that it is correctly destructed if there is an exception somewhere between its allocation and the return.


I would implement a destructor for BufferedReader that would destroy any used resources and free any memory used during that object's lifetime. After I did that, then I would call delete on my BufferedReader object.

Of course, that would be if you were using C++ only.


You might want to start with looking here.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜