C ++使用任意长度和格式的行读取多行文件而不使用字符串流

时间:2012-11-22 10:17:53

标签: c++ stream inputstream

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

# <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这样的第三级数据结构。必须直接从流中读取用户提供的数据结构。

编辑:请注意我们只允许对文件进行一次传递。

2 个答案:

答案 0 :(得分:2)

  

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

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

  

这只适用于第一行,其中已知有一行   固定数量的元素。

  

(2)不幸的是,我不知道每个数据实例的鉴别器   结构需要用存储在三个中​​的信息来实例化   不同的线条。所有三条线都有不同的长度和不同   数据元素。另外,我无法更改格式。

<强>加

  

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

现在下一个问题是我们不知道数据结构究竟是什么,所以考虑到之前的情况,它似乎在某种程度上是动态的。因为我们可以将数据视为unsigned 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.

答案 1 :(得分:1)

然后根本不要使用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或直接操纵流缓冲区。