C++在不使用字符串流的情况下读取具有任意长度和格式的行的多行文件

C++ Reading an multiline file with lines with arbitary lengths and format without using a stringstream

本文关键字:任意长 格式 文件 读取 字符串 情况下 C++      更新时间:2023-10-16

我有一个包含以下行的输入流:

# <int> <int>
<some_data_type> <some_data_type> <some_data_type> ..... <some_data_type>
<some_data_type_1> <some_data_type_2> <some_data_type_3> <some_data_type_1> <some_data_type_2> <some_data_type_3> .... <some_data_type_1> <some_data_type_2> <some_data_type_3> 

在上面的流中,所有三行都是不同的,必须以不同的方式进行解析。目前,我使用的阅读方法如下:

void reader( std::istream & is, DataStructure & d ){
std::string line;
getline(is,line);
std::stringstream s(line);
//parse line 1
getline(is,line);
std::stringstream line2(line);
//parse line 2
getline(is,line);
std::stringstream line3(line);
//parse line 3
}

现在的想法是根本不使用std::stringstream,因为一条线可以任意大,我们不想把所有东西都加载到内存中两次。因此,如果可以从输入流直接读取到用户给定的数据结构d.中,那就更好了

一个想法是使用std::istream_iterator,但不幸的是,不同的行有不同的解析需求。例如,在最后一行中,流中的三个元素一起构成单个数据元素。

在我看来,目前唯一可行的想法是直接处理流缓冲区。如果有人能推荐一种更好的方法,那就太好了。

注意:不能使用像std::stringstream这样的第三级数据结构。从流中直接读取到用户提供的数据结构中是至关重要的。

编辑:请注意,我们只允许对文件进行一次检查。

现在的想法是根本不使用std::stringstream,作为一行可以任意大,并且我们不想将所有内容都加载到内存中两次因此,如果能够从直接输入流到用户给定的数据结构d.

Olaf解释了上面的提取运算符,但我们有了一个新的要求:

这只适用于已知存在固定数量的元素。

(2)不幸的是,除了我所知道的数据的每个实例之外,我没有鉴别器结构需要用存储在三个中的信息进行实例化不同的线路。这三条线的长度不同数据元素。此外,我无法更改格式。

加上

(3)所有信息都被视为无符号整数。

现在的下一个问题是,我们不知道数据结构实际上是什么,所以考虑到之前的情况,它在某种程度上看起来是动态的。因为我们可以将数据视为无符号int,所以我们可以使用提取运算符,但读取到动态成员中:

vector<unsigned int> myUInts;
...
inFile >> currentUInt;
myUInts.push_back(currentUInt);

但是,在哪里停下来的问题开始发挥作用。它在第一行,第三行的末尾吗?如果你需要读取任意数量的无符号整数,同时仍在检查新行,那么你也需要处理空白:

inFile.unsetf(ios_base::skipws);

在没有更明确要求的情况下,你实际上是如何处理的,这超出了我目前所能说的范围。但我想它会以的形式出现

inFile >> myMember;
char next = infile.peek()
//skip whitespace and check for new line
//Repeat until data structure filled, and repeat for each data structure.

然后根本不要使用std::getline()。为您的类型定义一个istream运算符,并直接使用这些

std::istream &operator >>(std::istream &f, DataStructure &d)
{
f >> d.member1 >> d.member2 >> ...;
return f;
}
void reader(std::istream & is, DataStructure &d)
{
is >> d;
}

不需要摆弄std::istream_iterator或直接操作流缓冲区。