php 拆分文件

背景

工作中有遇到一些场景,处理某些文件时因为数据量太多太大了而导致处理时间非常长,并且大概率会处理失败。所以参考了网上的一些资料:php 处理拆分文件,不会从行中间切断。

先看效果

大文件拆分为4个文件

[root@iZt4nijo6mcpzvyciap0kaZ HongXunPan]# ll -h
total 4.1M
-rw-r--r-- 1 root root 4.1M May 23 17:19 test.txt
[root@iZt4nijo6mcpzvyciap0kaZ HongXunPan]# vim test.php
-rw-r--r-- 1 root root     961 May 23 17:20 test.php
-rw-r--r-- 1 root root 4276536 May 23 17:19 test.txt
[root@iZt4nijo6mcpzvyciap0kaZ HongXunPan]# /usr/local/php/bin/php test.php 
[root@iZt4nijo6mcpzvyciap0kaZ HongXunPan]# ll -h
total 8.2M
-rw-r--r-- 1 root root  961 May 23 17:20 test.php
-rw-r--r-- 1 root root 4.1M May 23 17:19 test.txt
-rw-r--r-- 1 root root 1.1M May 23 17:21 test.txt_0
-rw-r--r-- 1 root root 1.1M May 23 17:21 test.txt_1
-rw-r--r-- 1 root root 1.1M May 23 17:21 test.txt_2
-rw-r--r-- 1 root root 1.1M May 23 17:21 test.txt_3

拆分为10个文件

[root@iZt4nijo6mcpzvyciap0kaZ HongXunPan]# /usr/local/php/bin/php test.php 
[root@iZt4nijo6mcpzvyciap0kaZ HongXunPan]# ll -h
total 8.2M
-rw-r--r-- 1 root root  962 May 23 17:29 test.php
-rw-r--r-- 1 root root 4.1M May 23 17:28 test.txt
-rw-r--r-- 1 root root 418K May 25 19:45 test.txt_0
-rw-r--r-- 1 root root 418K May 25 19:45 test.txt_1
-rw-r--r-- 1 root root 418K May 25 19:45 test.txt_2
-rw-r--r-- 1 root root 418K May 25 19:45 test.txt_3
-rw-r--r-- 1 root root 418K May 25 19:45 test.txt_4
-rw-r--r-- 1 root root 418K May 25 19:45 test.txt_5
-rw-r--r-- 1 root root 418K May 25 19:45 test.txt_6
-rw-r--r-- 1 root root 418K May 25 19:45 test.txt_7
-rw-r--r-- 1 root root 418K May 25 19:45 test.txt_8
-rw-r--r-- 1 root root 418K May 25 19:45 test.txt_9

源码

test.php

<?php

$filename = './test.txt';
$file = fopen($filename,'r+') or die('fail');
$filenum = 4; //拆分成新文件的数量
$filelen = ceil(filesize($filename)/$filenum);  //每个新文件的长度
rewind($file);  //指针设置到文件开头0的位置
$lastlen = 0;
for ($i = 0; $i< $filenum ; $i++)
{
    $content = fread($file, $filelen + $lastlen);   //等长字符串,加上上一个字符串不足一行的部分
    $lastn = strrchr($content, "\n");   //不足一行的字符串
    $lastlen = strlen($lastn);  //不足一行的字符串长度
    $complete = substr($content, 0, strlen($content) - $lastlen);   //减去当前字符串不足一行的部分,得到每一行都完整的字符串
    //写入新文件
    $newfile = fopen($filename. '_' . $i, 'w+');
    fwrite($newfile, $complete);
    fseek($file, ftell($file) - $lastlen + 1);  //将文件指针返回到不足一行的开头,使下一个文件能得到完整行

}
fclose($file);