Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 空间不足时将数据写入文件开头_Php_File - Fatal编程技术网

Php 空间不足时将数据写入文件开头

Php 空间不足时将数据写入文件开头,php,file,Php,File,问题 若我并没有足够的空间在RAM中分配数据,又并没有足够的空间在当前FS分区上复制数据,那个么如何将数据写入文件的开头?也就是说,我有一个大小为100Mb的文件,我的PHP脚本中有30Mb内存限制(并且它不能以任何方式进行调整),我当前的FS分区上只有50Mb可用空间。我想在文件中添加2-10行(肯定少于剩余的50Mb FS空间) 一些背景 我知道并同意这件事是真的。但为了重新考虑这个案例,我需要更改当前应用程序的重要部分(实际上,它来自于以前的团队),可能是使用此文件的其他应用程序的API

问题

若我并没有足够的空间在RAM中分配数据,又并没有足够的空间在当前FS分区上复制数据,那个么如何将数据写入文件的开头?也就是说,我有一个大小为
100Mb
的文件,我的PHP脚本中有
30Mb
内存限制(并且它不能以任何方式进行调整),我当前的FS分区上只有
50Mb
可用空间。我想在文件中添加2-10行(肯定少于剩余的50Mb FS空间)

一些背景

我知道并同意这件事是真的。但为了重新考虑这个案例,我需要更改当前应用程序的重要部分(实际上,它来自于以前的团队),可能是使用此文件的其他应用程序的API

我的尝试

我还没有找到解决这个问题的办法。我以前的方法是-使用一些网络缓冲区(例如,连接到一些外部存储,例如MySQL-它位于另一台有足够空间写入文件副本的机器上)

问题


所以,当我并没有足够的空间在RAM中分配数据,也并没有足够的空间在FS上创建文件副本时,是否有可能将数据写入文件的开头?使用网络(外部)存储是唯一的解决方案吗?

如果要在文件开头写入2K,唯一的实际选择是:

  • 打开文件
  • 从文件末尾读取尽可能多的内容,以便放入内存
  • 在开始读取之前,将其写回文件2K
  • 继续上一个数据块,直到将文件2K的整个内容移到末尾
  • 把你的2K写在开头
设想:

|------------------------|

|-----------------XXXXXXX|
                  ------>

|-------------------XXXXXXX|

|----------XXXXXXX---------|
           ------>

|------------XXXXXXX-------|

...repeat...

请注意,这是一个非常不安全的操作,它会在位编辑文件。如果进程崩溃,您将看到一个处于不一致状态的文件。如果磁盘上没有足够的空间来复制文件,可以说不应该先处理该文件并扩展存储容量。

@deceze告诉我一个好主意。因此,我已经完成了:

function reverseFile($sIn, $sOut, $bRemoveSource=false)
{
        $rFile = @fopen($sIn, 'a+');
        $rTemp = @fopen($sOut,'a+');
        if(!$rFile || !$rTemp)
        {
                return false;
        }
        $iPos = filesize($sIn)-1;
        while($iPos>=0)
        {
                fseek($rFile, $iPos, SEEK_SET);
                fwrite($rTemp, $tmp=fread($rFile, 1));
                ftruncate($rFile, $iPos>0?$iPos:0);
                clearstatcache();
                $iPos--;
        }
        fclose($rFile);
        fclose($rTemp);
        if($bRemoveSource)
        {
                unlink($sIn);
        }
        return true;
}

function writeReverse($sFile, $sData, $sTemp=null)
{
        if(!isset($sTemp))
        {
                $sTemp=$sFile.'.rev';
        }
        if(reverseFile($sFile, $sTemp, 1))
        {
                file_put_contents($sTemp, strrev($sData), FILE_APPEND);
                return reverseFile($sTemp, $sFile, 1);
        }
        return false;
}
-这将非常缓慢,但如果进程中断,则可以恢复(只需查看
.rev
文件)


感谢所有参与此活动的人。

我已经尝试过@AlmaDo建议的代码,不要在实际项目中尝试,否则你会被烧死,速度非常慢。(60MB文件-处理19分钟)

您可以运行shell脚本-(已处理420ms,无法理解它使用了多少内存)
或者试试这个php脚本-(160ms,使用内存限制=3M,不使用2M)

看看这些答案:@ComFreek-很遗憾,我在那里没有找到想要的解决方案-但是谢谢你。这里有我尝试过的所有选项(甚至不适用于
fopen($rFile,'a+')
倒带
(与
fseek
相同)仅供参考,我发现了一个,它似乎无法将整个文件加载到内存中。是的,我喜欢这个,因为它至少可以工作。我正在考虑您提到的案例-如果书写过程将被中断,该怎么办再次感谢您-我受您的想法启发,创建了安全的方法来实现这一点。