我正在学习C ++,我必须以二进制模式读取文件。这是我的方式(遵循C ++参考):
unsigned values[255];
unsigned total;
ifstream in ("test.txt", ifstream::binary);
while(in.good()){
unsigned val = in.get();
if(in.good()){
values[val]++;
total++;
cout << val <<endl;
}
}
in.close();
所以,我正在读取每个字节的文件字节,直到in.good()
为真。我在cout
的末尾放了一些while
以了解发生了什么,这是输出:
marco@iceland:~/workspace/huffman$ ./main
97
97
97
97
10
98
98
10
99
99
99
99
10
100
100
10
101
101
10
221497852
marco@iceland:~/workspace/huffman$
现在,输入文件“test.txt”只是:
aaaa
bb
cccc
dd
ee
所以一切都很完美,直到最后,那里有221497852.我猜这是关于文件结尾的东西,但我无法解决问题。
我正在使用gedit&amp;在debian机器上的g ++(64位)。 任何帮助将不胜感激。
非常感谢,
马
答案 0 :(得分:3)
fstream::get
会返回int
- 值。这是其中一个问题。
其次,您正在阅读二进制,因此您不应使用格式化的流。您应该使用fstream::read
:
// read a file into memory
#include <iostream> // std::cout
#include <fstream> // std::ifstream
int main () {
std::ifstream is ("test.txt", std::ifstream::binary);
if (is) {
// get length of file:
is.seekg (0, is.end);
int length = is.tellg();
is.seekg (0, is.beg);
char * buffer = new char [length];
std::cout << "Reading " << length << " characters... ";
// read data as a block:
is.read (buffer,length);
if (is)
std::cout << "all characters read successfully.";
else
std::cout << "error: only " << is.gcount() << " could be read";
is.close();
// ...buffer contains the entire file...
delete[] buffer;
}
return 0;
}
答案 1 :(得分:1)
这不是istream::get()
设计使用的方式。
使用这个函数的经典习语是:
for ( int val = in.get(); val != EOF; val = in.get() ) {
// ...
}
或甚至更惯用:
char ch;
while ( in.get( ch ) ) {
// ...
}
第一个循环实际上是从C继承的,其中in.get()
是
相当于fgetc()
。
尽管如此,据我所知,您提供的代码应该工作。 这不是惯用的,它不是
C ++标准尚不清楚它应该返回什么
读取的字符值为负数。 fgetc()
需要输入值
范围[0...UCHAR_MAX]
,我认为可以安全地假设
这是 intent 。它至少是每一个
我用过的实现。但这不会影响你的
输入。取决于实现如何解释
标准,in.get()
的返回值必须在范围内
[0...UCHAR_MAX]
或[CHAR_MIN...CHAR_MAX]
,或者必须是EOF
(通常为-1)。 (我很确定意图的原因
要求[0...UCHAR_MAX]
是因为否则,你可能不会
能够区分文件末尾和有效字符。)
和如果返回值是EOF(几乎总是
-1),failbit
应该设置,因此in.good()
将返回
false
。有否的情况允许in.get()
返回221497852.我能想到的唯一解释
对于您的结果是您的文件有一些字符
第7位设置在文件的末尾,实现是
为此返回一个负数(但不是文件末尾,
因为它是一个字符),导致越界
values[val]
中的索引,以及此超出范围的索引
不知何故最终修改val
。或者你的实现是
已损坏,并且在返回结束时未设置failbit
文件。
可以肯定的是,我有兴趣知道你从中获得了什么 以下内容:
std::ifstream in( "text.txt", std::ios_base::binary );
int ch = in.get();
while ( ch != std::istream::traits_type::eof() ) {
std::cout << ch << std::endl;
ch = in.get();
}
这可以避免任何可能无效的索引和任何类型的问题
转化(虽然转化int
到unsigned
很好
定义)。此外,出于好奇(因为我只能访问VC ++
在这里,您可以尝试按以下方式替换in
:
std::istringstream in( "\n\xE5" );
我希望得到:
10
233
(假设8位字节和基于ASCII的代码集。两者都有 这几乎是,但今天不太普遍。)
答案 2 :(得分:-1)
我最终想出来了。 显然,问题似乎不是由于任何代码。问题是gedit。它总是在文件末尾附加换行符。这也发生在其他编辑器上,例如vim。对于某些编辑器,这可以配置为不附加任何内容,但在gedit中,这显然是不可能的。 https://askubuntu.com/questions/13317/how-to-stop-gedit-gvim-vim-nano-from-adding-end-of-file-newline-char
欢迎所有问我的人,
马