带有UNIX格式字符的getline()文本

时间:2012-08-21 16:25:28

标签: c++ ascii text-files special-characters getline

我正在编写一个C ++程序,它从.txt文件中读取文本行。不幸的是,文本文件是由一个二十多年前的UNIX程序生成的,它包含许多奇怪的格式化字符。

文件的前几行是普通的英文文本,这些文字都没有问题。但是,每当一行包含与文本混合的一个或多个这些奇怪字符时,整行将被读作 字符并且数据将丢失。

真正令人困惑的部分是,如果我手动删除前几行,以便文件中的第一个字符是这些不常见的字符之一,那么文件中的所有内容都将被完美读取。这些不同寻常的角色显然只是显示出一点点曲线 - 箭头,笑脸等,这很好。似乎是在没有我的知情或同意的情况下根据第一行阅读自动做出决定。

基于一些谷歌搜索,我怀疑问题可能出在语言环境中,但根据visual studio调试器,ifstream对象的locale属性在两种情况下都是“C”。

读取数据的代码如下:

//Function to open file at location specified by inFilePath, load and process data
int OpenFile(const char* inFilePath)
{
    string line;
    ifstream codeFile;

    //open text file
    codeFile.open(inFilePath,ios::in);

    //read file line by line
    while ( codeFile.good() )
    {
       getline(codeFile,line);

       //check non-zero length
       if (line != "")
            ProcessLine(&line[0]);
    }

    //close line
    codeFile.close();

    return 1;
}

如果有人对可能发生的事情或如何解决问题有任何建议,他们会非常欢迎。

1 个答案:

答案 0 :(得分:0)

从阅读你的问题看起来,你正在阅读二进制数据,这将导致getline()丢弃内容或只是跳过该行。

您有几个选择:

  1. 如果您只需要数据文件中的行,则可以先删除所有不可打印的字符(即那些奇怪的ascii字符的“官方”名称)来清理它们。在UNIX上,诸如strings之类的工具可以帮助您完成该过程。

    您可以在代码中以编程方式执行此操作,只需读取X数据量,将其存储在字符串中,然后删除那些超出标准ASCII字符范围的字符。这很可能会导致您丢失可能存储在文件中的任何unicode。

  2. 您更改程序以理解格式,并且基本上编写一个解析器,允许您以更加理智的方式解析文档。
  3. 如果可以的话,我建议尝试1号解决方案,只是为了看看结果是否合理并且仍然可以使用。你提到这是医学数据,你是否有机会知道这是什么文件格式?如果你想找到并且可以访问unix / linux机器,你可以使用实用程序file,也许它可以给你一个线索(最坏的情况是它会告诉你它只是数据)。

    如果可能,请尝试获取一个“干净”文件,您可以发布十六进制转储,以便我们可以尝试提供比我们目前提供的更好的帮助。干净,我的意思是文件中没有个人识别信息。


    对于数字2,以二进制模式打开文件。您提到使用Windows,std :: fstream对象中的二进制和非二进制文件的处理方式不同,而在UNIX系统上则不是这样(在大多数系统上,我确信我会得到关于一个系统的评论与此描述不符。)

    codeFile.open(inFilePath,ios::in);
    

    会变成

    codeFile.open(inFilePath, ios::in | ios::binary);
    

    而不是getline(),您将希望与.read()密切相关,这将允许对ifstream进行无格式操作。

    阅读将是这样的:

    // This code has not been tested!
    char input[1024];
    codeFile.read(input, 1024);
    
    int actual_read = codeFile.gcount();
    
    // Here you can process input, up to a maximum of actual_read characters.
    
    //ProcessLine() // We didn't necessarily read a line!
    ProcessData(input, actual_read);
    

    提到的另一件事是您可以更改当前流的locale并更改它认为是新行的分隔符,这可能会解决您的问题而无需使用未格式化的运算符:

    imbue the stream with a new locale that only knows about the newline。这个方法可能会也可能不会让你的getline()函数没有问题。