3

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

文件的前几行是纯英文文本,可以毫无问题地阅读。但是,每当一行包含一个或多个这些奇怪的字符与文本混合时,整行都会被读取为 字符并且数据会丢失。

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

根据一些谷歌搜索,我怀疑问题可能与语言环境有关,但根据 Visual Studio 调试器,在这两种情况下,ifstream 对象的语言环境属性都是“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;
}

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

4

1 回答 1

0

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

你有几个选择:

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

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

  2. 您更改程序以了解格式并基本上编写一个解析器,允许您以更理智的方式解析文档。

如果可以的话,我建议尝试第 1 种解决方案,看看结果是否合理并且仍然可以使用。您提到这是医疗数据,您是否知道这是什么文件格式?如果您正在尝试查找并访问 unix/linux 机器,您可以使用该实用程序file,也许它可以为您提供线索(最坏的情况下它会告诉您它只是数据)。

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


对于数字 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当前流的 并更改它认为新行的分隔符,也许这将解决您的问题而无需使用未格式化的运算符:

用只知道换行符的新语言环境为流灌输。此方法可能会或可能不会让您的 getline() 正常运行。

于 2012-10-31T05:38:01.433 回答