Как избежать memcpy в буферизированном выводе C ++ - PullRequest
0 голосов
/ 27 апреля 2011

Я пытаюсь записать напрямую в выходной буфер fstream, чтобы избежать memcpy.

Почему следующий код не работает?

Он компилирует, запускает и создает выходной файл нужной длины в Linux. Но выходной файл не содержит правильный текст. Также обратите внимание, что по какой-то причине, когда я закомментирую две строки, включающие str2, создается выходной файл нулевой длины.

Примечание: Этот пример не избегает memcpy, но если он сработает, он поможет мне избежать memcpy в моем приложении.

#include <fstream>

int main(int argc, char *argv[]) {
  std::fstream out;
  char buffer[512];
  out.rdbuf()->pubsetbuf(buffer, 512);
  out.open("file.txt", std::fstream::out);
  char *str1 = "test text.";
  strcpy(buffer, str1);
  out.rdbuf()->pubseekpos(strlen(str1), std::ios_base::out);
  char *str2 = "why?";
  out << str2;
  out.flush();
  out.close();
}

Ответы [ 5 ]

2 голосов
/ 27 апреля 2011

Вы предоставляете потоку буфер для его внутреннего использования. Тогда ты ничего не пишешь.

Тот факт, что вы копируете что-то в буфер , не сообщая потоку , ничего не дает в файле.

Как вы могли заметить, seekpos предназначен для позиционирования в файле, а не для перемещения в буфере. Буфер предназначен только для внутреннего использования потока!

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

Когда вы out.rdbuf()->pubseekpos(strlen(str1), std::ios_base::out);, это просит поток пропустить вперед через вновь созданный файл.Можете ли вы ожидать, что он возьмет вещи из указанного вами буфера?Подсказка: вы видели какие-либо примеры, включающие указание буфера, в котором говорилось, что вам нужно каким-либо образом инициализировать его или указывать начальное количество не содержащих мусор символов, которые в нем содержатся?Нет ... потому что сам поток отслеживает, какие части буфера используются.Следовательно - когда вы берете предполагаемый пустой буфер и пропускаете вперед, он генерирует промежуточные NUL.Для них не имеет смысла устанавливать их в буфере (поэтому простое выполнение memcpy после pubseekpos тоже не сработает) - что если вы перепрыгнули больше, чем вперед, на размер буфера?

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

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

вижу три возможности

  1. Реализация собственного класса потокового буфера
  2. Использовать собственный файл API
  3. Отключить буферизацию с помощью pubsetbuf(0, 0)

Реализация потокового буфера на самом деле не так сложна, и даст вам возможность смешивать вставку потока в стиле C ++ с прямым доступом к памяти, без жертвуя производительностью.

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

Я недостаточно знаком с библиотекой C ++ iostream, чтобы сказать, что не так с вашей программой, я бы только упомянул, что если вы захотите сделать свою собственную буферизацию, то, вероятно, будет проще использовать read () и write() напрямую взаимодействует (man 2 write).Если вы делаете свою собственную буферизацию, библиотеки iostream, вероятно, не будут вам много покупать и будут только затемнять то, что происходит на самом деле.

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

Еще рано, но разве ты не делаешь

#include <fstream>

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

  std::fstream out;
  out.open("file.txt", std::fstream::out);

  out << "test text";
  out << "why?";

  out.flush();
  out.close();
}

...