C++ ifstream/fstream损坏数据
我是C++的新手,我必须为学校做一项任务。C++ ifstream/fstream损坏数据
我需要在不使用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 看着它后,我看到数据已经modefied,而我没有做任何事的
谁能帮助我?
*文件是一个简单的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
,你可以或在读取或写入过程字节被删除无法看到以某种方式(或增加,有时也会发生)
我认为
ifstream src(source.c_str(), ios::binary);
ofstream dest(destination.c_str(), ios::binary | ios::trunc);
dest << src.rdbuf();
src.close();
dest.close();
会做的伎俩。
除非您想检查错误(并且如果您不检查,则不要),否则不需要显式调用close。让它掉到范围之外,析构函数会清理干净。 – 2010-11-16 22:26:40
允许作出这样的一个位整洁:
// 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-17 17:58:19
@Dean辉光:它应该看起来像你的。但整理好了,整洁。 – 2010-11-17 18:31:46
传递仅ios_base::binary
到fstream
的构造函数未指定(in
和/或out
也必须被提供)。
为了避免这种情况,您可以使用ofstream
(注意ex'0')代替out
而不是fstream
。作为奖励,由于ofstream
的ctor在默认情况下创建文件,因此这将避免首先带有“w”标志的fopen
。
通常,文件以换行符结束。那0d0a(“\ r \ n”)可能不是源文件的可读部分。 Windows通常使用“\ r \ n”作为换行符,而UNIX只使用“\ n”。出于某种原因,当它写入一个新文件时,它仅使用0a作为最终换行符。如果您阅读并复制您第一次编写的文件,会发生什么情况可能会很有趣。
简而言之,这只是在使用Windows系统时遇到的那种问题。 :D
要破解它,你总是可以无条件地写一个额外的“\ r”作为你输出的最后一个东西。
您是否试过在十六进制编辑器中查看结果文件以查看它出错的位置?或者复制一个文本文件,比较容易? – 2010-11-16 20:39:45
你有什么样的问题?在函数中间随机打开了什么? – stonemetal 2010-11-16 20:42:27
它是如何修改的?输出与输入有什么不同? – 2010-11-16 20:43:18