Какой самый элегантный способ написать текстовый / двоичный файл с C ++? - PullRequest
3 голосов
/ 10 марта 2011

Я нашел некоторые хорошие результаты при чтении, например: Чтение txt с итераторами и предварительное распределение , или чтение в контейнеры . Поэтому я подумал, как бы я записал наиболее элегантный std :: string в файл?

Изменить: При чтении я могу предварительно выделить место для строки с помощью поиска и сообщения, так как я знаю размер строки, как я могу сказать файловой системе, сколько я хочу записать?

Ответы [ 3 ]

6 голосов
/ 10 марта 2011

Вот небольшой пример того, как вывести std::string, но вы действительно должны прочитать о fstream

#include <iostream>
#include <fstream>
#include <string>

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

  std::string s("writemeout");
  std::ofstream outfile("output.txt");
  if(!outfile.is_open()) {
    std::cerr << "Couldn't open 'output.txt'" << std::endl;
    return -1;
  }

  outfile << s << std::endl;
  outfile.close();
  return 0;
}
1 голос
/ 10 марта 2011

Основная проблема заключается в том, что процесс не полностью меняется.

std::ofstream ofs; // presumed open
ofs << v1 << v2 << v3 << v4 << v5; // some different variables
ofs.close();

std::ifsteram ifs; // open to same stream
ifs >> r1 >> r2 >> r3 >> r4 >> r5; // variables of same types as above

Вы можете подумать, что это сработает, но, вероятно, не сработает. При записи в текстовый поток формальных разделителей не существует, их необходимо вручную вставить, чтобы узнать, когда один токен заканчивается, а другой начинается.

Обычно в отношении строк предполагается, что они не содержат символов новой строки или символов табуляции, а затем при чтении они часто используются в качестве разделителя.

Самый «идеальный» способ написать строку, чтобы вы могли ее прочитать, - записать ее размер, а затем ее содержимое. Даже если вы используете iostream:

os << str.size() << str;

не будет ставить пробел между размером и содержимым, поэтому, если содержимое начинается с цифры, у вас возникают проблемы при ее чтении позже.

os << str.size() << '\t' << str;

будет работать.

Что касается чтения больших коллекций, вам лучше всего использовать строки со знаком табуляции или со строкой и использовать std :: getline в цикле. istream_iterator просто не будет работать, если в вашей строке есть пробелы.

Ваша альтернатива - сначала прочитать в разделе заголовка: - количество строк - размер каждой строки.

Затем считывайте данные только из большого буфера, и, зная, сколько вы собираетесь прочитать и их размеры, вы можете предварительно распределить свои буферы.

Запись двоичного кода означает запись необработанных байтов в файл. Это похоже на функцию fwrite в C, за исключением того, что вы не указываете два размера, только один размер, который является числом байтов, которые вы напишите.

Вам необходимо решить вопросы, которые: - Windows вставит для вас символ ASCII 13 перед каждым символом ASCII 10, который вы пишете, если вы не открываете поток для двоичного файла. - Если вы пишете числа побайтно, будьте осторожны с порядковыми номерами и размерами, если они будут прочитаны обратно. Лучший способ решить эту проблему - поместить порядковый номер в заголовочный раздел вашего вывода, а затем записать в собственном формате. Предполагается, что большую часть времени это будет платформа, которую вы используете, поэтому она более эффективна.

int x;
os.write( &x, sizeof(int) );

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

Недостатком является то, что вам потребуется специальный интерпретатор для чтения файла обратно, если в нем есть какие-либо ошибки.

В любом случае, это проблемы.

Элегантное решение для всего этого предоставляется в составе библиотеки наддува с архивом и сериализацией .

Вы можете писать в текстовом или двоичном режиме, и он восстановит способ, которым вы его сохранили. Он даже будет писать указатели «глубоко» для вас.

1 голос
/ 10 марта 2011

Вы можете использовать соответствующую перегрузку функции operator<< для записи строки в объект std::ofstream.Вот пример:

#include <fstream>
#include <string>

int main() {
    std::string s( "Hello, World!" );
    std::ofstream f( "hello.txt" );
    if ( !f.fail() )
        f << s;
}
...