2009-07-17 25 views
1

我正在编写一个生成大输出文件的C程序。为了提高可读性,我想在文件中的某些点收集某些类型的输出,而不是随机分散。在输出文件中的两点之间移动

考虑像一个文件:

log 
log 
(a) 

output 
output 
output(b) 

说,项目目前正在写的线在(B)。在C中有一种特别优雅的方式来实现移动到点(a)的效果,在(b)处添加一个线输出,然后恢复正常输出?

我知道我可以通过使用标准shell工具(如csplit)来在特定点打破文件,将输出追加到前半部分,然后再将它们放在一起。但是,这个应用程序必须是跨平台的,所以我不能指望有一个可用的shell。

任何建议将是最有帮助的!

+1

需要您只有一个输出文件吗?这对于每种输出类型使用不同的文件似乎更直观(也更简单!)。 – 2009-07-17 16:54:24

+0

是的,它是必需的。输出文件实际上是另一个程序的一组命令(LaTeX的TikZ图形绘图包是特定的)。我试图将某些命令集分组在一起,以使输出更易于阅读。 – Sharpie 2009-07-17 17:01:50

回答

6

在单个文件中执行所描述的操作的唯一方法是预先为“日志”条目预留所需的所有空间,我猜测您无法做到这一点,因为你不知道他们会有多大。

您不能只是插入到文件中,向上移动插入点上方的内容以腾出空间。这不是普通文件系统支持的概念。您需要物理读取并重新写入所有“输出”部分才能插入“日志”部分,随着文件的增长,这需要越来越多的工作。

最好的办法是编写两个单独的文件,然后在最后加入到一起。

编辑以下记号笔的评论:由于输出是一组程序命令的,这是否意味着你可以安全地假设它永远不会超过几MB大的多,刚刚建造起来。记忆之前,一口气写完了吗?

+0

我们最大的测试运行目前产生一个2.1 MB的输入文件,我猜测它可以轻松地提高一个数量级。它看起来像写一些临时文件并将它们拼接在一起可能是要走的路。 – Sharpie 2009-07-17 17:12:01

+1

+1“写入2个文件并在最后加入” – AShelly 2009-07-17 17:13:18

+0

我会为拼接投票。除非有预先确定文件将要多长的时间。 – NoMoreZealots 2009-07-17 17:56:24

0

fgetpos你可以存储一个指向一个位置的文件并跳转到它在任何时候fseek

0

C或C++?如果使用C++,可以使用seekp()来定位输出指针。这只会让你覆盖,但。

+0

不幸的是,我们没有使用C++。感谢指针虽然 - 我一定会检查出来,如果我碰到相同的问题在C + +! – Sharpie 2009-07-17 16:59:18

2

这是一个非常不寻常的要求。

一种方法是将前缀区分字符串用于两种 输出行,然后将它们写入同一文件中。当你想要一组特定的输出时,grep为他们在组合文件中。

output.txt ...
MARK1:登录
MARK2:输出
MARK-1:登录
MARK2:输出
MARK2:输出

grep "^MARK1:" output.txt 
grep "^MARK2:" output.txt 

您最终将需要的文件,你希望它写出来。
为此,您将需要截断的前缀字符串。
当时它是,如果你使用的是相匹配的简单正则表达式
喜欢的东西串很容易,

sed 's/^MARK.://g' output.txt > filtered.txt 
4

你不能这样做直接的原因很简单:

有没有办法在文件中间插入字节。您只能将覆盖一段文件或附加到文件末尾。

如果你要插入一个文件的中间,你有两个选择:

  • 阅读所有的位置后要插入到内存中的字节数。然后编写你想要插入的部分,然后将你缓存的所有字节写入内存。结果将会是字节被插入给定的位置,代价是任意大的内存块来容纳你必须“推回”的块。
  • 或者,您将所有内容写入新文件。将源文件中的字节复制到新文件中。如果您想要插入新数据,请写下新行。然后继续从原始文件复制,直到完成。这不需要大量的内存,但需要使用临时文件来存储组合结果。

...

  • 或者另外,不直接写你的输出到一个文件,但把一切都在内存中,并把它写命令的输出文件一旦你完成收集日志线。
+0

我特别同意“在提交文件之前保留内存中的日志行列表”一点。 – 2009-07-17 17:23:17