【问题标题】:Ifstream reads wrong characters from text fileifstream 从文本文件中读取错误的字符
【发布时间】:2012-02-08 16:07:12
【问题描述】:

我有以下简单的代码,它将文本文件的内容读入字符数组:

const char* name = "test.txt";
std::cout << "Loading file " << name << std::endl;
std::ifstream file;
file.open(name);
file.seekg (0, std::ios::end);
int length = file.tellg();
std::cout << "Size: " << length << " bytes" << std::endl;
file.seekg (0, std::ios::beg);
char* buffer = new char[length];
file.read(buffer,length);
file.close();
std::cout.write(buffer,length);

但是,ifstream 似乎从文件中读取了错误数量的字符:每行增加 1 个字符。我在网上搜索,看起来在win7文本文件中除了每行末尾的换行符(\n)外,还有回车符(\r)。但是,流不知何故看不到这些 \r,但仍使用文件中的原始符号数,从文件末尾读取额外的字节。有没有办法解决这个问题?

如果有帮助:我使用 MinGW 编译器和 Windows 7 64 位。

【问题讨论】:

  • 也许您可以改用readsome 函数,看看您实际阅读了多少?

标签: c++ io


【解决方案1】:

阅读有关为binary 阅读打开文件的信息(谷歌或查看here)。

【讨论】:

    【解决方案2】:

    您可能希望以二进制模式打开文件:

    file.open(name, ios_base::in | ios_base::binary);
    

    否则,标准库会为您将每个 Windows 换行符 (CR+LF) 转换为单个 \n。

    这意味着您可以从文件中读取的字符数与文件的大小不同。当您调用read() 时,它会读取尽可能多的字符。如果它无法读取您请求的字符数,它会设置流的failbit。

    【讨论】:

    • 在 Windows 上。不一定在其他系统上。
    【解决方案3】:

    您是从一些非常错误(但普遍)的观点开始的。 file.tellg() 不返回 int;它返回一个实现 streampos 类型的定义对象,它必须是类类型,并且可以 或者可能无法转换为整数类型。如果是 可转换为整数类型(我不知道实现 如果不是,即使它不是必需的),也不能保证 结果整数代表的不仅仅是一个魔术饼干,它 将允许重新搜索到相同的位置。

    实际上,这在现代机器上可能不是什么大问题:两者 Unix 和 Windows 返回文件开头的偏移量(以字节为单位)。 在 Unix 的情况下,这很好用,因为 对外部的内部表示是一对一的。在这种情况下 在 Windows 中,对行尾进行了重新映射:在文本文件中,一行 结尾是一个 0x0D、0x0A 的两字节序列,读取时变为 单个字符'\n'。和streampos(转换为整型) 以字节为单位给出您必须在文件中查找的位置,而不是 您必须读取的字符数才能到达该位置。为了这些事 就像您似乎在做的那样,这不是问题;分配的 缓冲区可能比必要的大一点,但永远不会太大 小。

    请注意,这在大型机上可能并非如此。历史上,在 至少,大型机使用面向块的文件,以及 a 的整数值 streampos 很容易被分解成字段,带有 块号的某些位,字节的其他位 块中的偏移量。取决于这些在单词中的排列方式, 像您一样分配的缓冲区可能很容易达到几个数量级 太大,或者如果偏移量放在高位上,就太小了。

    获得所需缓冲区确切大小的唯一可靠方法是 取决于系统,并且在某些系统(包括 Windows)上,可能有 除了阅读所有字符并数数之外别无他法。

    (streampos 必须是类类型的原因是, 从历史上看,许多较旧的多字节编码都有编码状态;你 在不知道什么字符的情况下无法正确解码字符 在它之前。所以streampos需要包含两个不同的 信息:在文件中寻找的位置,以及关于 这种状态。我不认为有任何依赖于状态的多字节 然而,当今广泛使用的编码。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-17
      • 2011-12-28
      • 1970-01-01
      • 2020-07-04
      • 2012-11-13
      相关资源
      最近更新 更多