gpt4 book ai didi

php - 操作一个 3000 万字符长的字符串

转载 作者:行者123 更新时间:2023-12-02 03:32:01 25 4
gpt4 key购买 nike

我正在从另一台服务器下载 CSV 文件作为供应商的数据源。

我使用curl 获取文件的内容并将其保存到名为$contents 的变量中。

我可以很好地到达该部分,但我尝试通过 \r\n 爆炸来获取行数组,但失败并显示“out of”内存错误。

echo strlen($contents),它大约有 3050 万个字符。

我需要操作这些值并将它们插入数据库。我需要做什么才能避免内存分配错误?

最佳答案

正如其他答案所说:

  • 你无法记住所有这些
  • 解决方案是使用CURLOPT_FILE

但是,您可能不想真正创建一个您可能想要处理内存中数据的文件......在它“到达”后立即使用它。

一种可能的解决方案可能是定义您自己的流包装器,并通过 CURLOPT_FILE 使用这个流包装器,而不是真实的文件

首先,请参阅:


现在,让我们来看一个例子。

首先,让我们创建流包装类:

class MyStream {
protected $buffer;

function stream_open($path, $mode, $options, &$opened_path) {
// Has to be declared, it seems...
return true;
}

public function stream_write($data) {
// Extract the lines ; on y tests, data was 8192 bytes long ; never more
$lines = explode("\n", $data);

// The buffer contains the end of the last line from previous time
// => Is goes at the beginning of the first line we are getting this time
$lines[0] = $this->buffer . $lines[0];

// And the last line os only partial
// => save it for next time, and remove it from the list this time
$nb_lines = count($lines);
$this->buffer = $lines[$nb_lines-1];
unset($lines[$nb_lines-1]);

// Here, do your work with the lines you have in the buffer
var_dump($lines);
echo '<hr />';

return strlen($data);
}
}

我所做的是:

  • 当数据 block 到达时对其进行处理(我使用 var_dump,但你会做你平常的事情)
  • 请注意,您不会得到“整行”:行的末尾是 block 的开头,而同一行的开头位于前一个 block 的末尾,因此,您必须保留一些部分对 stream_write
  • 的调用之间的一个 block


接下来,我们注册此流包装器,以与伪协议(protocol)“test”一起使用:

// Register the wrapper
stream_wrapper_register("test", "MyStream")
or die("Failed to register protocol");


现在,我们执行 curl 请求,就像写入“真实”文件时所做的那样,就像建议的其他答案一样:

// Open the "file"
$fp = fopen("test://MyTestVariableInMemory", "r+");

// Configuration of curl
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.rue89.com/");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 256);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FILE, $fp); // Data will be sent to our stream ;-)

curl_exec($ch);

curl_close($ch);

// Don't forget to close the "file" / stream
fclose($fp);

请注意,我们不使用真实文件,而是使用伪协议(protocol)。


这样,每当一大块数据到达时,MyStream::stream_write方法就会被调用,并且能够处理少量数据(当我测试时,我总是得到8192 字节,无论我用于 CURLOPT_BUFFERSIZE 的值)


一些注意事项:

  • 显然,你需要比我更多地测试这个
  • 如果行长度超过 8192 字节,我的 Stream_write 实现可能无法工作,需要您来修补它;-)
  • 这只是一些提示,而不是一个完整的解决方案:您必须(再次)测试,并且可能需要编写更多代码!

不过,我希望这会有所帮助;-)
玩得开心!

关于php - 操作一个 3000 万字符长的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1342583/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com