我们可以来回移动ofstream指针以输出到文件吗?

时间:2018-03-31 06:08:57

标签: c++ file output ofstream

我需要将结果输出到具有预定义格式的文件。列看起来像这样:

TIME COL1 COL2 COL3 COL4 ......

我正在使用ofstream。我必须逐行输出结果。但是,情况可能是某些列的结果可能在某个时间不可用。结果的顺序也可能没有排序。

我可以在最初指定标题时控制列之间的间距。

我想我的问题是:是否可以每行水平来回移动ofstream指针?

到目前为止我尝试了什么:
1)使用以下方法找到流指针的当前位置:

long pos = fout.tellp()

2)根据间距计算要移位的位置:

spacing = column_spacing * column_number 
long newpos = pos + spacing  

3)然后使用seekp()移动指针:

fout.seekp(newpos)    

4)提供输出:

fout << "output"  

这不起作用。基本上,指针不移动。我的想法是尽可能让我的ofstream fout来回移动。我很感激有关如何控制它的任何建议。

有关输出的一些信息:我正在计算天空中GPS卫星的仰角随时间的变化。因此,总共有32个列与GPS卫星的数量同义。在任何时间点,并非所有卫星都是可见的,因此需要跳过一些卫星/列。此外,由于观察文件的限制,卫星的高程列表可能不按升序排列。希望有助于绘制情况。

所需输出的示例。标题(TIME,SAT1,... SAT32)是在输出结果之前定义的,并不是此处问题的一部分。在定义标题期间控制每列之间的间距(假设每列之间有15个空格)。输出可以截断为1位小数。一旦写入当前时间t的所有结果,就会出现新行。然后我处理时间t + 1的观察结果,然后再次写入输出,依此类推。因此,写作以一种流行的方式发生。卫星高程存储在矢量(双)中,卫星编号存储在矢量(int)中。两个向量具有相同的长度。我只需要将它们写入文件。对于下面的示例,时间输出以秒为单位,卫星高程以度为单位:

TIME   SAT1   SAT2   SAT3   ...   SAT12   SAT13  ...   SAT32
1      34.3          23.2         12.2                 78.2
2      34.2          23.1         12.3                 78.2
3      34.1   11.3   23.0                              78.3  

依此类推......正如您所注意到的那样,卫星升高可能会也可能不会出现,一切都取决于观测结果。让我们假设输出和效率的大小在这里不是优先考虑的。根据24小时的观察结果,输出文件大小可以达到5-10 MB。

感谢您提前的时间!

1 个答案:

答案 0 :(得分:5)

  

我们可以来回移动ofstream指针以输出到文件吗?

,你可能不想这样做(即使它原则上是可行的;但这样做效率低,编码非常脆弱,几乎无法调试) ,特别是对于宽度可变的文本输出(我猜你的COL i 可以像大多数文本格式一样具有可变宽度)。看起来你的方法是错误的。

一般的方法是在内存中构建一些&#34;对象&#34;或&#34;数据结构&#34;,输出文件的整个表示。这通常就足够了,除非你真的需要输出一些巨大的东西。

如果典型的文本输出大小合适(最多几千兆字节),那么将数据表示为一些内部数据结构是值得的,这是很常见的做法。

如果您的文本输出很大(几十千兆字节或太字节,这是不太可能),那么您将无法在内存中表示它(除非您有一台昂贵的计算机和一兆兆字节的RAM)。但是,您可以使用某个数据库(可能是sqlite)作为内部表示。

实际上,文本格式总是按顺序输出(来自某些内部表示),并且这些格式的文本文件具有合理的大小(因此,今天拥有一个千兆字节的文本文件是不常见的;在这种情况下,数据库 - 或者在某些目录中将输出文件分成几部分 - 会更好。)

未指定精确您的文本格式(例如使用EBNF表示法)并举例 - 以及输出大小的一些估算 - 您的问题太宽泛了,你只能得到上面的提示。

  

输出文件大小最多可达5-10 MB

这在当前的计算机上实际上很小(即使是便宜的智能手机也有一个千兆字节的RAM)。因此,在内存中构建数据结构,并在完成后立即输出。

您应该使用data structures取决于您的实际问题(以及您的程序获得的输入以及您希望它生成的精确输出)。由于您未在问题中指定您的计划,我们无法帮助您。可能C ++标准containerssmart pointers可能有用(但这只是猜测)。

你应该阅读一些编程的介绍(比如SICP),然后阅读一些好的C++ programming书并阅读一些好的Introduction to Algorithms。您可能需要阅读有关编译技术的内容(因为它们包括解析和输出结构化数据),例如Dragon Book。学习大量时间编程takes

C ++实际上是一种非常困难的编程语言,我相信它不是学习编程的最佳方式。一旦你学会了如何编程,就把时间花在学习C ++上。您的问题不在std::ostream或C ++上,而在于正确设计程序及其架构

顺便说一句,如果您的程序输出正在为一些其他程序提供(并且不仅仅是或主要供人类使用),您可以使用一些既定的文本格式,可能是JSONYAML,{{ 3}},CSV(另见XML示例),....

     2      34.2          23.1         12.3                 78.2

上一行中的空格有多重要(如果在第一个2之后插入空格而另一个空格在12.3之后被删除会发生什么?)?您的输出中是否会出现3.14159265358979323846264这样的广泛数字?或者你想要几位数?那应该在某处记录正好!您是否可以改进上面的输出格式(您可能会使用?这样的符号来表示缺少的数字;这会使输出更加模糊,对人类更具可读性,更容易被其他程序this使用)?

您需要精确定义 (英文)程序的行为,包括其输入和输出格式。输入和输出的示例不是规范(仅作为示例)。

顺便说一句,您可能还希望对程序进行编码以提供多种不同的输出格式。例如,您可以决定在speadsheets中使用CSV格式,为其他数据处理提供JSON格式,parse输出以获得更好的数字,gnuplot输出以便能够在某些技术报告中插入您的输出,LaTeX输出可以通过浏览器等使用。一旦你有一个良好的内部表示(作为方便的数据结构)你的计算数据,以各种格式输出它很容易,非常方便。

您的域(卫星处理)可能已经定义了一些广泛使用的数据格式。详细研究它们(至少有关于指定自己的输出格式的灵感)。我不是卫星数据的专家,但是谷歌我很快就找到了像HTML这样的例子(超过一百页)。您应该像他们一样精确地指定您的输出格式(可能是几十页的英文页面,有几页GEOSCIENCE AUSTRALIA (CCRS) LANDSAT THE MATIC MAPPER DIGITAL DATA FORMAT DESCRIPTION),而EBNF是一个方便的表示法(有很多额外的)解释用英语)

还要了解其他输出数据格式描述的灵感。

如果您发明输出格式,您可能应该发布其规范(英文版),以便其他人可以编写将输出作为其代码输入的程序。

在许多领域,数据比处理它的代码更有价值(即成本更高,欧元或美元)。这就是为什么它的格式应该准确记录。您需要指定该格式,以便2030年的未来程序员可以轻松地为其编写解析器。所以细节很重要。 明确指定输出格式的详细信息(在某些英文文档中)。

一旦指定了输出格式,就可以轻松地从一些足够好的内部数据表示中编写输出例程(并且不需要疯狂的技巧,比如移动输出的文件偏移量)。输出格式的足够规范也是设计内部数据表示的指导原则。

  

是否可以每行水平前后移动ofstream指针?

它可能是可行的,但它是如此低效且容易出错(并且无法调试),在实践中你永远不应该这样做(而是详细说明你的输出和代码a简单的顺序输出例程,就像所有与文本格式相关的软件一样)。

BTW,今天我们在文本文件中使用EBNF,而单个UTF-8 everywhere编码的UTF-8字符可能跨越一个(例如某些数字,如0或拉丁字母,如E)或几个字节(例如é等强调字母,或я等西里尔字母,或等符号......)因此替换单个UTF8另一个字符可能意味着某些字节插入或删除。

请注意,当前文件系统不允许插入字符或字节或删除文件中间的字符范围(例如,在Linux上,那里是没有Unicode允许这个)并且并不真正了解行(行尾只是约定,例如Linux上的\n字节)。这样做的程序(如您最喜欢的syscalls(2)总是表示内存中的数据。今天,source code editor是一个字节序列,你只能在其末尾附加字节,或者在中间替换字节(从操作系统的角度来看);但是在文件中间插入或删除字节跨度是不可能的,这就是文本文件在实践中始终按顺序从头到尾写入的原因,而不是在当前文件偏移量内移动(除了附加字节)在它的结尾)。

(如果这是一些CS学院或本科课程的作业,我想你的老师希望你定义并记录你的输出格式)