C++ 二进制文件 I/O,写入时数据丢失
C++ binary files I/O, data lost when writing
我正在通过 Bjarne Stroustrup 的“编程:使用 C++ 的原理和实践”一书学习 C++。我目前正在学习第 11 章,我找到了一个关于如何 读取和写入整数的二进制文件 的示例(第 11.3.2 节)。我尝试了这个例子,并使用了一个 .txt 文件 (input.txt) 和一个句子,我读取并写入另一个文件 (output.txt) (text_to_binary fnc) 然后读取和写入回到原始文件 (input.txt) (binary_to_text fnc).
#include<fstream>
#include<iostream>
using namespace std;
void text_to_binary(ifstream &ifs, ofstream &ofs)
{
for (int x; ifs.read(as_bytes(x), sizeof(char));)
{
ofs << x << '\n';
}
ofs.close();
ifs.close();
}
void binary_to_text(ifstream &ifs, ofstream &ofs)
{
for (int x; ifs >> x;)
{
ofs.write(as_bytes(x), sizeof(char));
}
ifs.close();
ofs.close();
}
int main()
{
string iname = "./chapter_11/input.txt";
string oname = "./chapter_11/output.txt";
ifstream ifs{iname, ios_base::binary};
ofstream ofs{oname, ios_base::binary};
text_to_binary(ifs, ofs);
ifstream ifs2{oname, ios_base::binary};
ofstream ofs2{iname, ios_base::binary};
binary_to_text(ifs2, ofs2);
return 0;
}
我发现我必须在 .read 和 .write 中使用 sizeof(char) 而不是 sizeof(int)命令。如果我使用 sizeof(int),当我将它们写回文本时,.txt 文件的某些字符会丢失。有趣的是,只有在
时才会丢失足够多的字符
x%4 != 0 (x = nb of chars in .txt file)
带有 sizeof(int) 的示例:
input.txt:
hello this is an amazing test. 1234 is a number everything else doesn't matter..asd
(text_to_binary fnc) 结果:
output.txt:
1819043176
1752440943
1763734377
1851859059
1634558240
1735289210
1936028704
824192628
540291890
1629516649
1836412448
544367970
1919252069
1768453241
1696622446
543519596
1936027492
544483182
1953784173
774795877
(binary_to_text fnc) 结果返回:
input.txt:
hello this is an amazing test. 1234 is a number everything else doesn't matter..
asd 失踪了。
现在回答我的问题,为什么会发生这种情况?是因为int的存为4字节吗?
奖金问题:出于兴趣,是否有 simpler/more 有效的方法来做到这一点?
编辑:用结果更新了问题,希望更清楚
当您尝试进行部分读取时,读取将尝试超出文件末尾,并且将为流设置 eof
标志。这使得它在循环条件 false
中使用,因此循环结束。
您需要在 循环后检查流 的 gcount
以查看是否有任何字节实际读入变量 x
.
但是请注意,部分读取只会写入变量的一部分x
,剩下的不确定。具体哪些部分取决于系统 endianness,并且使用具有不确定位的变量将导致 未定义的行为。
我正在通过 Bjarne Stroustrup 的“编程:使用 C++ 的原理和实践”一书学习 C++。我目前正在学习第 11 章,我找到了一个关于如何 读取和写入整数的二进制文件 的示例(第 11.3.2 节)。我尝试了这个例子,并使用了一个 .txt 文件 (input.txt) 和一个句子,我读取并写入另一个文件 (output.txt) (text_to_binary fnc) 然后读取和写入回到原始文件 (input.txt) (binary_to_text fnc).
#include<fstream>
#include<iostream>
using namespace std;
void text_to_binary(ifstream &ifs, ofstream &ofs)
{
for (int x; ifs.read(as_bytes(x), sizeof(char));)
{
ofs << x << '\n';
}
ofs.close();
ifs.close();
}
void binary_to_text(ifstream &ifs, ofstream &ofs)
{
for (int x; ifs >> x;)
{
ofs.write(as_bytes(x), sizeof(char));
}
ifs.close();
ofs.close();
}
int main()
{
string iname = "./chapter_11/input.txt";
string oname = "./chapter_11/output.txt";
ifstream ifs{iname, ios_base::binary};
ofstream ofs{oname, ios_base::binary};
text_to_binary(ifs, ofs);
ifstream ifs2{oname, ios_base::binary};
ofstream ofs2{iname, ios_base::binary};
binary_to_text(ifs2, ofs2);
return 0;
}
我发现我必须在 .read 和 .write 中使用 sizeof(char) 而不是 sizeof(int)命令。如果我使用 sizeof(int),当我将它们写回文本时,.txt 文件的某些字符会丢失。有趣的是,只有在
时才会丢失足够多的字符x%4 != 0 (x = nb of chars in .txt file)
带有 sizeof(int) 的示例:
input.txt:
hello this is an amazing test. 1234 is a number everything else doesn't matter..asd
(text_to_binary fnc) 结果:
output.txt:
1819043176
1752440943
1763734377
1851859059
1634558240
1735289210
1936028704
824192628
540291890
1629516649
1836412448
544367970
1919252069
1768453241
1696622446
543519596
1936027492
544483182
1953784173
774795877
(binary_to_text fnc) 结果返回:
input.txt:
hello this is an amazing test. 1234 is a number everything else doesn't matter..
asd 失踪了。
现在回答我的问题,为什么会发生这种情况?是因为int的存为4字节吗?
奖金问题:出于兴趣,是否有 simpler/more 有效的方法来做到这一点?
编辑:用结果更新了问题,希望更清楚
当您尝试进行部分读取时,读取将尝试超出文件末尾,并且将为流设置 eof
标志。这使得它在循环条件 false
中使用,因此循环结束。
您需要在 循环后检查流 的 gcount
以查看是否有任何字节实际读入变量 x
.
但是请注意,部分读取只会写入变量的一部分x
,剩下的不确定。具体哪些部分取决于系统 endianness,并且使用具有不确定位的变量将导致 未定义的行为。