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

Can we move the pointer of ofstream back and forth for output to file?

本文关键字:输出 文件 指针 移动 我们      更新时间:2023-10-16

我需要将结果输出到具有预定义格式的文件中。这些列如下所示:

时间 COL1 COL2 COL3 COL4 ...

我正在使用流。我必须逐行输出结果。但是,某些列的结果可能在特定时间不可用。结果的顺序也可能不排序。

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

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

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

long pos = fout.tellp()

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

spacing = column_spacing * column_number 
long newpos = pos + spacing  

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

fout.seekp(newpos)    

4)提供输出:

fout << "output"  

这行不通。基本上,指针不会移动。这个想法是让 如果可能的话,让我的流 fout 来回移动。我将不胜感激任何关于如何控制它的建议。

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

所需输出的示例。标头(时间、SAT1、...SAT32)是在结果输出之前定义的,不是这里问题的一部分。每列之间的间距在定义标题期间控制(假设每列之间有 15 个空格)。输出可以截断为小数点后 1 位。写入当前时间 t 的所有结果后,将出现一个新行。然后我处理时间 t+1 的观测值,然后再次写入输出,依此类推。 因此,写作以划时代的方式发生。卫星高程存储在矢量(double)中,卫星编号存储在矢量(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。

提前感谢您的时间!

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

,您可能不想这样做(即使原则上可行;但这效率低下且代码非常脆弱,几乎不可能调试),特别是对于宽度可变的文本输出(我猜您的 COLi可以具有可变宽度,就像大多数文本格式中通常一样)。 看来你的方法错了。

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

如果您的典型文本输出具有合理的大小(最多几千兆字节),那么将数据表示为某种内部数据结构是值得的,这是非常普遍的做法。

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

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

如果没有精确指定您的文本格式(例如使用 EBNF 表示法)并给出示例 - 以及对输出大小的一些估计 - 您的问题太宽泛,您只能得到上述提示。

输出文件大小可以达到5-10 MB

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

您应该使用什么数据结构取决于您的实际问题(以及程序获得的输入以及您希望它生成的精确输出)。由于您没有在问题中指定您的程序,因此我们无法提供帮助。可能C++标准容器和智能指针可能有用(但这只是一个猜测)。

你应该阅读一些编程的介绍(如SICP),然后阅读一些好的C++编程书籍,并阅读一些好的算法导论。你可能需要阅读一些关于编译技术的东西(因为它们包括解析和输出结构化数据),比如龙书。学习编程需要很多时间。

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

顺便说一句,如果您的程序的输出正在馈送其他程序(并且不仅或主要供人类使用),您可能会使用一些已建立的文本格式,也许是JSON,YAML,CSV,XML(另请参阅此示例),....

2      34.2          23.1         12.3                 78.2

上行中的空格有多重要(如果在第一个2之后插入一个空格,而在12.3之后删除另一个空格会发生什么)?像3.14159265358979323846264这样的大量数字可以出现在您的输出中吗?或者你想要多少位数?这应该在某处精确记录!您是否可以改进上面的输出格式(您可能会使用一些符号,例如?来表示丢失的数字;这将使输出不那么模糊,对人类来说更具可读性,并且更容易被其他程序解析)?

您需要精确地(用英语)定义程序的行为,包括其输入和输出格式。输入和输出的示例不是规范(它只是一个示例)。

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

可能您的域(卫星处理)已经定义了一些广泛使用的数据格式。详细研究它们(至少是为了获得指定自己的输出格式的灵感)。 我根本不是卫星数据专家,但通过谷歌,我很快就找到了像澳大利亚地球科学这样的例子 (中新社)LANDSAT MATIC MAPPER 数字数据格式 描述(一百多页)。您应该像它们一样精确地指定输出格式(可能是几十页的英文,还有几页的 EBNF),而 EBNF 是一种方便的符号(有很多额外的英文解释)

还可以从其他输出数据格式描述中寻找灵感。

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

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

指定输出格式后,从一些足够好的内部数据表示中对输出例程进行编码很容易(并且不需要像移动输出的文件偏移量这样的疯狂技巧)。输出格式的足够好的规范也是设计内部数据表示的指南。

是否可以每行水平来回移动流指针?

这可能是可行的,但它效率低下且容易出错(并且无法调试),以至于在实践中您永远不应该这样做(而是详细指定您的输出并编写一个简单的顺序输出例程,就像所有文本格式相关软件一样)。

顺便说一句,今天我们在文本文件中到处都使用 UTF-8,单个 UTF-8 编码的 Unicode 字符可能跨越一个(例如,对于某些数字,如0或拉丁字母,如E)或几个字节(例如,对于重音字母,如é,或西里尔字母,如я,或符号,如等),因此用另一个字符替换单个 UTF8 字符可能意味着一些字节插入或删除。

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

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