【问题标题】:C++ reading from file puts three weird charactersC++ 从文件中读取三个奇怪的字符
【发布时间】:2012-05-12 03:43:54
【问题描述】:

当我逐个字符串读取文件时,>> 操作获取第一个字符串,但它以 "i" 开头。假设第一个字符串是“street”,而不是“itreet”。

其他字符串没问题。我尝试了不同的txt文件。结果是一样的。第一个字符串以“i”开头。有什么问题?

这是我的代码:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;

int cube(int x){ return (x*x*x);}

int main(){

int maxChar;
int lineLength=0;
int cost=0;

cout<<"Enter the max char per line... : ";
cin>>maxChar;
cout<<endl<<"Max char per line is : "<<maxChar<<endl;

fstream inFile("bla.txt",ios::in);

if (!inFile) {
    cerr << "Unable to open file datafile.txt";
    exit(1);   // call system to stop
}

while(!inFile.eof()) {
    string word;

    inFile >> word;
    cout<<word<<endl;
    cout<<word.length()<<endl;
    if(word.length()+lineLength<=maxChar){
        lineLength +=(word.length()+1);
    }
    else {
        cost+=cube(maxChar-(lineLength-1));
        lineLength=(word.length()+1);
    }   
}

}

【问题讨论】:

  • Aside:从不使用.eof()作为循环条件。它几乎总是会产生错误的代码,就像您的情况一样。更喜欢在循环条件下做输入操作:string word; while(inFile &gt;&gt; word) { … }.

标签: c++ file-io byte-order-mark


【解决方案1】:

您看到的是 UTF-8 Byte Order Mark (BOM)。它是由创建文件的应用程序添加的。

要检测并忽略标记,您可以尝试这个(未经测试的)功能:

bool SkipBOM(std::istream & in)
{
    char test[4] = {0};
    in.read(test, 3);
    if (strcmp(test, "\xEF\xBB\xBF") == 0)
        return true;
    in.seekg(0);
    return false;
}

【讨论】:

  • 另外你可能想提一下他读错了文件;它应该是 while (inFile &gt;&gt; word) 而不是 while (!inFile.eof())
  • 除非你在 if 语句之前添加一个 "(unsigned char)" 强制转换,否则上面的代码将不起作用,例如if ((unsigned char)test[0] == 0xEF && (unsigned char)test[1] == 0xBB && (unsigned char)test[2] == 0xBF)。要么,要么与 -17、-69 和 -65 进行比较。请参阅下面的答案。
  • @Contango,我不知道为什么我花了这么长时间才看到你的评论,但谢谢。我想出了一个完全不同的方法来解决这个问题,请参阅我的最新编辑。
【解决方案2】:

这是另外两个想法。

  1. 如果您是创建文件的人,请将它们的长度与它们一起保存,并在读取它们时,只需通过以下简单计算删除所有前缀:trueFileLength - savedFileLength = numOfByesToCut
  2. 在保存文件时创建自己的前缀,在阅读时搜索并删除之前找到的所有内容。

【讨论】:

    【解决方案3】:

    参考上面 Mark Ransom 的出色回答,添加此代码会跳过现有流上的 BOM(字节顺序标记)。打开文件后调用它。

    // Skips the Byte Order Mark (BOM) that defines UTF-8 in some text files.
    void SkipBOM(std::ifstream &in)
    {
        char test[3] = {0};
        in.read(test, 3);
        if ((unsigned char)test[0] == 0xEF && 
            (unsigned char)test[1] == 0xBB && 
            (unsigned char)test[2] == 0xBF)
        {
            return;
        }
        in.seekg(0);
    }
    

    使用方法:

    ifstream in(path);
    SkipBOM(in);
    string line;
    while (getline(in, line))
    {
        // Process lines of input here.
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-02-23
      • 1970-01-01
      • 2017-11-16
      • 1970-01-01
      • 2022-11-07
      • 2017-01-19
      相关资源
      最近更新 更多