【问题标题】:Use fwrite() at a certain position without overwriting content [duplicate]在某个位置使用 fwrite() 而不会覆盖内容 [重复]
【发布时间】:2016-09-10 08:43:10
【问题描述】:

编辑:对于其他寻找答案的人,我使用了this。可能是解决问题的最快方法。


假设我有一个 非常 大的 test.txt 文件,其中包含:

line1
line4
line5
line6

我希望在第 1 行之后添加第 2 行和第 3 行。我使用以下代码来实现这一点:

$file = fopen('test.txt', 'r+');
fseek($file, 5);
fwrite($file, "\r\nline2\r\nline3\r\n");

但是,txt 文件现在变成了,第 4 行和第 5 行被覆盖:

line1
line2
line3
line6

我在fopen 中使用c+ 模式得到相同的结果。我不能使用aa+,因为它们只是将内容附加到文件末尾。我也无法将整个文件读入一个字符串并对其进行分析以进行更改,因为这个文件真的很大。

有什么办法可以解决这个问题?

注意:由于文件中的大量内容,任何涉及将整个文件作为字符串读取然后从那里进行更改的解决方案都不可行。如果有任何厚颜无耻的变通方法可以在第一行和第二行之间的几行中添加内容,那就足够了。 :D

【问题讨论】:

  • 您不能简单地将新内容添加到文件中间;文件系统不会在您插入新字符时将所有内容打乱,实际上您必须自己编写代码来执行此操作....通常打开 1 个文件用于读取,1 个用于写入,然后在最后重命名
  • 一般你可以stream copy从第一个文件到第二个文件直到你的搜索位置,然后手动将你的新内容添加到第二个文件,然后将剩余内容从搜索位置流式复制到末尾文件
  • 您可以添加足够的空白空间来为您提供插入 2 行的空间,然后复制该行,然后重新插入它和另一行。虽然这并不理想,因为每一行都需要空格,并且在您添加/覆盖行时它会降级(您只能添加与留下空白空间一样多的数据)。它还会不必要地膨胀文件大小。基本问题是每个字节(字符)在文件中都有一个位置,就像网格上的钉子一样。要查找,只需将指针移动到网格单元,然后从那里写入,覆盖网格单元中现有的钉子。
  • 只有纯php?如果文件真的很大 - 尝试exec 使用:` gawk -i inplace -v n=line_number -v s="content" 'NR == n {print s} {print}' path_to_file`

标签: php


【解决方案1】:

遗憾的是,fopen 和朋友不允许插入,只能追加。从他们的角度来看,该文件是一个大的、可增长的数组。因此,没有调用插入数据,只有覆盖。

但是,您可以通过多种方式解决此问题。一种简单的方法是使用afwrite 从原始文件的第 1 行打开一个临时文件,附加第 2 行和第 3 行,然后将原始文件的其余部分分块写入临时文件。一旦你传输了整个文件(注意,不要一次将整个文件加载到内存中),然后你可以将临时文件移动到原始文件的顶部。

【讨论】:

    【解决方案2】:

    您可以通过从每一行创建一个数组来做到这一点。然后将搜索到的行替换为您想要的任何内容。

    $searchLine = 'line1'; 
    $file = getcwd()."test.txt";
    $lineArray = file( $file , FILE_IGNORE_NEW_LINES ); 
    $lineArray[$searchLine] =  $searchLine."\r\nline2\r\nline3\r\n"; // Replace the line with new ones
    file_put_contents( $filename , implode( PHP_EOL, $lineArray) ); // Put the content
    

    【讨论】:

    • 问题是文件非常非常大,所以这可能不可行。
    • @chris97ong 用 preg_replace 替换这些行怎么样?我不知道正则表达式是否适合这个,但只是一个想法。
    • @mertizici 任何需要读取整个文件内容的解决方案都不太可行:/
    • @chris97ong - 使用任何文件流函数都可以处理最大整数(32 位或 64 位)的文件。像fread 这样的流式一次只读取文件的一小部分,然后重用内存。读取一个大文件可能需要一些时间,但我已经设法读取了超过 1000 万行和千兆字节大小的文件。如果我没记错的话,我认为(2GB)是 32 位系统的限制。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-28
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 2020-06-07
    • 2019-10-05
    相关资源
    最近更新 更多