Копирование содержимого одного файла в другой в C ++ - PullRequest
3 голосов
/ 29 сентября 2010

Я использую следующую программу, чтобы попытаться скопировать содержимое файла, src, в другой, dest, в C ++.Упрощенный код приведен ниже:

#include <fstream>
using namespace std;
int main()
{
  fstream src("c:\\tplat\test\\secClassMf19.txt", fstream::binary);
  ofstream dest("c:\\tplat\\test\\mf19b.txt", fstream::trunc|fstream::binary);
  dest << src.rdbuf();
  return 0;
}

Когда я собрал и выполнил программу, используя CODEBLOCKS ide с компилятором GCC в Windows, был создан новый файл с именем ".... mf19.txt", но нетданные были скопированы в него, а размер файла = 0 КБ.Я уверен, что у меня есть некоторые данные в "... secClassMf19.txt".

Я сталкиваюсь с той же проблемой, когда я скомпилировал ту же программу в Windows Visual C ++ 2008.

Может кто-нибудь, пожалуйста, помогитеобъясните, почему у меня такое неожиданное поведение, и, что более важно, как решить проблему?

Ответы [ 3 ]

4 голосов
/ 29 сентября 2010

Перед использованием этих потоков необходимо проверить, действительно ли открытие файлов прошло успешно.Кроме того, никогда не повредит проверить, все ли прошло правильно после этого.Измените свой код на это и сообщите:

int main()
{
    std::fstream src("c:\\tplat\test\\secClassMf19.txt", std::ios::binary);
    if(!src.good())
    {
        std::cerr << "error opening input file\n";
        std::exit(1);
    }
    std::ofstream dest("c:\\tplat\\test\\mf19b.txt", std::ios::trunc|std::ios::binary);
    if(!dest.good())
    {
        std::cerr << "error opening output file\n";
        std::exit(2);
    }
    dest << src.rdbuf();
    if(!src.eof())
        std::cerr << "reading from file failed\n";
    if(!dst.good())
        std::cerr << "writing to file failed\n";
    return 0;
}

Бьюсь об заклад, вы сообщите, что один из первых двух проверок попадет

Если открыть входной файл не удается, попробуйте открыть его, используя std::ios::in|std::ios::binary вместо std::ios::binary.

1 голос
/ 29 сентября 2010

Как написано, ваш src экземпляр является обычным fstream, и вы не указываете открытый режим для ввода. Простое решение - сделать src экземпляром ifstream, и ваш код работает. (Просто добавив один байт!)

Если бы вы проверили входной поток (как предлагает sbi), вы бы обнаружили, что он не был открыт правильно, поэтому ваш целевой файл имел нулевой размер. Он был открыт в режиме записи (так как это был ofstream) с параметром усечения, чтобы сделать его нулевым, но запись результата rdbuf() просто не удалась, ничего не написано.

Еще одна вещь, на которую следует обратить внимание, это то, что, хотя она отлично работает для небольших файлов, она будет очень неэффективна для больших файлов. Таким образом, вы читаете все содержимое исходного файла в память, а затем снова записываете его в один большой блок. Это тратит впустую много памяти. Вам лучше читать чанками (скажем, 1 МБ, например, разумный размер для дискового кэша) и записывать чанк за раз, причем последний является оставшимся размером. Чтобы определить размер источника, вы можете искать до конца и запрашивать смещение файла, тогда вы знаете, сколько байтов вы обрабатываете.

И вы, вероятно, обнаружите, что ваша ОС еще более эффективна при копировании файлов, если вы используете нативный API, но тогда она станет менее переносимой. Возможно, вы захотите взглянуть на модуль файловой системы Boost для портативного решения.

1 голос
/ 29 сентября 2010

Есть ли у вас причины не использовать функцию CopyFile ?

Best

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...