1

我是 C++ 新手,我必须为学校做作业。

我需要在不使用 api 调用或系统集成命令的情况下复制二进制 * 文件。在学校,我们使用 Windows 机器。

我搜索了一下,发现在不使用任何 api 的情况下复制数据的最佳方法是使用 iostream (ifstream/fstream) 这是我正在使用的代码:

int Open(string Name){

  int length;
  char * buffer;
  ifstream is;
  fstream out;
  FILE* pFile;
  is.open (Name.c_str(), ios::binary );

  // get length of file:
  is.seekg (0, ios::end);
  length = is.tellg();
  is.seekg (0, ios::beg);

  // allocate memory:
  buffer = new char [length];

  // read data as a block:
  is.read (buffer,length);
  is.close();

   pFile = fopen ( "out.exe" , "w" );
   fclose(pFile);

  out.open("out.exe", ios::binary);

  out.write( buffer, length);

  out.close();

  delete[] buffer;
  return 0;
}

out.exe 无法正常工作,在 winhex.exe 中查看后,我发现数据已被修改,而我没有对其进行任何操作

谁能帮我?

*该文件是一个简单的 hello world 程序,它的消息框是“hello world”

编辑:

对不起,我的反应迟钝,它正在睡觉。无论如何,我已经在十六进制编辑器中打开了两个(结果和原始)程序。似乎我尝试了这条线:

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

00000200   4C 00 00 00 00 30 00 00  00 02 00 00 00 0D 0A 00   L    0     

更改为:

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

00000200   4C 00 00 00 00 30 00 00  00 02 00 00 00 0A 00 00   L    0    

正如您在读取或写入过程中可以或看不到的那样,一个字节正在被删除(或添加,有时也会发生)

4

5 回答 5

2

未指定 传递ios_base::binary给's ctor(和/或也必须提供)。fstreaminout

为避免这种情况,您可以使用ofstream(注意 exra 'o')out代替fstream. 作为奖励,这将避免首先fopen使用“w”标志,因为ofstreamctor 默认创建文件。

于 2010-11-18T21:53:35.143 回答
1

让我们让它更整洁一点:

// Pass strings by const reference (just good habit)
// But may also save a copy. And it indicates that the function should
// not be messing with the name!
int Open(std::string const& Name, std::string const& out)
{
  // Declare variables as close to use as possable.
  // It is very C-Like to declare all the variables at the
  // head of a function.

  // Use the constructor to open the file.
  std::ifstream is(Name.c_str(), ios::binary);
  if (!is) // Failed to open
  {    return -1;
  }

  // get length of file:
  is.seekg (0, ios::end);
  std::size_t length = is.tellg();  // Use the correct type. int is not correct
  is.seekg (0, ios::beg);

  // allocate memory:
  // Using new/delete is risky. It makes the code not exception safe.
  // Also because you have to manually tidy up the buffer you can not
  // escape early. By using RAII the cleanup becomes automative and there
  // is no need to track resources that need to be tidied.
  // 
  // Look up the concept of RAII it makes C++ lfe so much easier.
  // std::vector implements the new/delete internally using RAII
  std::vector<char>    buffer(length);

  std::size_t  read = 0;
  do
  {
      // read does not gurantee that it will read everything asked for.
      // so you need to do int a loop if you want to read the whole thing
      // into a buffer.
      is.read(&buffer[read], length - read);
      std::size_t amount = is.gcount();
      if (amount == 0)
      {    return -2; // Something went wrong and it failed to read.
      }
      read += amount;
  } while(length != read);


  fstream out(out.c_str(), ios::binary );
  if (!out)
  {    return -3; // you may want to test this before spending all the time reading
  }


  // Probably need to loop like we did for read.
  out.write( &buffer[0], length);

  return 0;
}
于 2010-11-16T22:06:57.980 回答
1

is.read(buffer, length) 不能保证读取长度字节。

我忘记了 out.write 是否也是如此。

于 2010-11-16T20:46:54.513 回答
1

通常,文件以换行符结尾。那个 0d0a ("\r\n") 可能不是源文件的可读部分。Windows 通常使用“\r\n”作为换行符,而 UNIX 只使用“\n”。出于某种原因,当它写入一个新文件时,它只使用 0a 作为最后的换行符。如果您读入并复制您第一次编写的文件,看看会发生什么可能会很有趣。

简短的回答是,这只是您使用 Windows 系统时出现的问题。:D

要破解它,你总是可以无条件地写一个额外的“\r”作为你输出的最后一个东西。

于 2015-01-29T21:22:28.890 回答
0

我觉得

ifstream src(source.c_str(), ios::binary);
ofstream dest(destination.c_str(), ios::binary | ios::trunc);
dest << src.rdbuf();
src.close();
dest.close();

会成功的。

于 2010-11-16T21:59:40.347 回答