C ++ IO против Java IO - PullRequest
       45

C ++ IO против Java IO

1 голос
/ 20 апреля 2011

Обратите внимание, что это НЕ обсуждение "лучше, чем".

Я программист на Java, и это заставляет меня чувствовать себя невероятно глупым, не зная, как сделать очень много операций ввода-вывода для C ++.

Мне нужно сделать очень простой адаптер для синтаксических анализаторов XML, как показано в коде ниже:

В Java я мог бы просто использовать:

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

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

return xmlParser11.parse(xml);

Самый большой вопрос для меня - чтосделать с этим reader в C ++

Большое спасибо!

edit cutted;)

Ответы [ 7 ]

6 голосов
/ 20 апреля 2011

Чтобы дать более мягкое представление, следующий код C ++ имитирует ваш Java-код настолько, насколько это разумно:

#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';
}

Но, конечно, не нужно зацикливаться, чтобы прочитать входной поток в строкув C ++: входной поток может быть представлен в виде пары итераторов, которые могут использоваться различными способами:

#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';
}

Но часто временный строковый объект даже не нужен: синтаксический анализатор C ++ может работать свходной поток или пара итераторов напрямую.

3 голосов
/ 20 апреля 2011

Если вы читаете из файла, вы можете сделать это так:

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

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

Это прочитает весь файл в std::stringstream xml, включая разрывы строк и все (как в вашем примере кода) Затем вы можете получить к нему доступ как std::string, используя xml.str().

1 голос
/ 20 апреля 2011

Несколько комментариев по редактированию:

  • Было бы крайне редко принимать в качестве аргумента `std :: ifstream &`, а не `std :: istream &`.Единственный раз, когда вы видите `std :: ifstream`, это когда вы определяете сам объект.
  • Ошибка проверки того, успешно ли вы открыли поток, или нет, принадлежит тому, где вы открылись, а не в какой-то функциис (что должно быть) с `std :: istream &`.(Вы не можете проверить, открыт ли `std :: istream` или нет, потому что для многих типов потоков концепция" open "не существует.)
  • Не ясно, какова семантика«XML» - это: являются ли они значением; в этом случае он поддерживает копирование и присваивание, вы никогда не выделяете его динамически и возвращаете по значению из `XMLParser11 :: Parse`;или это какой-то объект-сущность, в этом случае вы возвращаете указатель (или, возможно, `std :: auto_ptr`), чтобы особенно убедиться, что клиент знает, что он отвечает за его удаление.
  • В любом случае, если `XML` выделяется динамически, вы должны хранить его в` std :: auto_ptr` в `XMLParser11 :: Parse`, чтобы убедиться, что он корректно уничтожен, если между его распределением есть исключениеи возвращение.
1 голос
/ 20 апреля 2011

Вы можете сделать то же самое в 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';
}

Возможно, это не лучшее решение, но оно уже довольно хорошее.Вероятно, я бы написал что-то вроде:

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

(обратите внимание, что необходим хотя бы один набор дополнительных скобок из-за аномалии в том, как C ++ будет анализировать оператор в противном случае.)

Или даже:

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

(Смотри, ма, без переменных :-)!) Оба эти решения сохраняют переводы строк в исходном файле, поэтому вам не нужно вставлять их обратно после прочтения.

1 голос
/ 20 апреля 2011

Это использует STL - вы хотели спросить о C ++ или вы хотите получить эквивалент C (то есть, используя fopen, fread и т. Д.)?

// 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;
}
0 голосов
/ 20 апреля 2011

Вы можете начать с поиска здесь .

0 голосов
/ 20 апреля 2011

Я бы реализовал деструктор для BufferedReader, который уничтожил бы любые используемые ресурсы и освободил бы всю память, использованную в течение времени жизни этого объекта. После того, как я это сделал, я бы позвонил delete на мой BufferedReader объект.

Конечно, это было бы, если бы вы использовали только C ++.

...