我是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
在阅读或写作过程中你可以或不可能看到一个字节被删除(或添加,有时也会发生)
答案 0 :(得分:1)
is.read(buffer,length)不保证读取长度字节。
我忘记了out.write是否也是如此。
答案 1 :(得分:1)
未指定 ios_base::binary
至fstream
的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;
}