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" が含まれています。

編集:

無反応でごめんなさい、寝てました。とにかく、16進エディタ内で(結果と元の)両方のプログラムを開きました。私はすべてこの行を試しているようです:

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

の ctor にのみ 渡すios_base::binaryことfstreamは指定されていません (inおよび/または指定するout必要があります)。

これを回避するには、代わりにforを使用できますofstream(exra 'o' に注意してください) 。おまけとして、これにより、最初に "w" フラグを付ける必要がなくなります。これは、 の ctor がデフォルトでファイルを作成するためです。outfstreamfopenofstream

于 2010-11-18T21:53:35.143 に答える
1

通常、ファイルは改行で終わります。その 0d0a ("\r\n") は、ソース ファイルの読み取り可能な部分ではない可能性があります。Windows では通常、改行に「\r\n」を使用しますが、UNIX では「\n」のみを使用します。何らかの理由で、新しいファイルを書き込むときに、最後の改行に 0a だけを使用しています。最初に書き込んだファイルを読み込んでコピーするとどうなるか興味深いかもしれません。

簡単に言えば、これは Windows システムを使用しているときに発生する問題のようなものです。:D

それをハックするには、最後に出力するものとして常に無条件に余分な「\r」を書くことができます。

于 2015-01-29T21:22:28.890 に答える
1

is.read(buffer, length) は length バイトを読み取ることが保証されていません。

同じことが out.write に当てはまるかどうかは忘れました。

于 2010-11-16T20:46:54.513 に答える
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 に答える
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 に答える