C ++ ifstream / fstream破坏数据

时间:2010-11-16 20:36:39

标签: c++ binary fstream ifstream

我是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    

在阅读或写作过程中你可以或不可能看到一个字节被删除(或添加,有时也会发生)

5 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

未指定 ios_base::binaryfstream的ctor未指定(in和/或out也必须提供)。< / p>

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

答案 2 :(得分:1)

通常,文件以换行符结尾。那个0d0a(&#34; \ r \ n&#34;)可能不是源文件的可读部分。 Windows通常使用&#34; \ r \ n&#34;对于换行,UNIX只使用&#34; \ n&#34;。出于某种原因,当它写一个新文件时,它只使用0a作为最终换行符。如果你读入并复制你第一次写的文件,可能会很有趣。

简而言之,这就是使用Windows系统时出现的问题。 :d

要破解它,你总是可以无条件地写一个额外的&#34; \ r&#34;作为你输出的最后一件事。

答案 3 :(得分:0)

我认为

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

会做到这一点。

答案 4 :(得分:0)

让我们更整洁:

// 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;
}