C++ ifstream/fstream corrupting data
我是C ++的新手,我必须做作业。
我需要在不使用api调用或系统集成命令的情况下复制二进制文件。在学校,我们使用Windows机器。
我搜索了一下,发现不使用任何api复制数据的最佳方法是使用iostream(ifstream / fstream)
这是我正在使用的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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"
编辑:
对不起,我反应迟钝,正在睡觉。
无论如何,我已经在十六进制编辑器中同时打开了(结果和原始)程序。
似乎我尝试了这一行:
1 2 3 | 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 |
更改为:
1 2 3 | 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 |
如您所知,在读取或写入过程中,字节已被删除(或添加,有时也会发生)
未指定仅将
为避免这种情况,您可以对
通常,文件以换行符结尾。 0d0a(" \ r \ n")可能不是源文件的可读部分。 Windows通常将" \ r \ n"用于换行符,而UNIX仅使用" \ n"。由于某种原因,当它写一个新文件时,它只使用0a作为最后的换行符。看看如果您读入并复制了第一次编写的文件会发生什么,可能会很有趣。
简短的答案是,这只是使用Windows系统时出现的那种问题。 :D
要破解它,您总是可以无条件地写一个额外的" \ r"作为最后输出的内容。
让我们稍微整洁一些:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | // 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; } |
is.read(buffer,length)不保证读取长度字节。
我忘了out.write是否同样如此。
我觉得
1 2 3 4 5 | ifstream src(source.c_str(), ios::binary); ofstream dest(destination.c_str(), ios::binary | ios::trunc); dest << src.rdbuf(); src.close(); dest.close(); |
会成功的