【问题标题】:Split a text file in PHP在 PHP 中拆分文本文件
【发布时间】:2011-01-03 21:29:04
【问题描述】:

如何使用 PHP 按字符数将大文本文件拆分为单独的文件?因此,每 1000 个字符拆分 10,000 个字符的文件将被拆分为 10 个文件。另外,找到句号后才能拆分吗?

谢谢。

更新 1:我喜欢 zombats 代码,我删除了一些错误并提出了以下内容,但有谁知道如何只在句号后拆分?

$i = 1;
    $fp = fopen("test.txt", "r");
    while(! feof($fp)) {
        $contents = fread($fp,1000);
        file_put_contents('new_file_'.$i.'.txt', $contents);
        $i++;
    }

更新 2: 我接受了 Zombats 的建议并将代码修改为下面的代码,它似乎可以工作 -

$i = 1;
    $fp = fopen("test.txt", "r");
    while(! feof($fp)) {
        $contents = fread($fp,20000);
        $contents .= stream_get_line($fp,1000,".");
        $contents .=".";

        file_put_contents("Split/".$tname."/"."new_file_".$i.".txt", $contents);
        $i++;
    }

【问题讨论】:

  • full stop /ˈˌfo͝ol ˈstäp/ 名词 (英国) — 使用的标点符号 (.)在句子或缩写词的结尾;一个句号。

标签: php string text-processing


【解决方案1】:

您应该能够使用基本的fread() 轻松完成此操作。您可以指定要读取的字节数,因此读取精确数量并将其输出到新文件是微不足道的。

试试这样的:

$i = 1;
$fp = fopen("test.txt",'r');
while(! feof($fp)) {
    $contents = fread($fp,1000);
    file_put_contents('new_file_'.$i.'.txt',$contents);
    $i++;
}

编辑

如果您希望在某个字符上达到一定长度后停止,那么您可以使用stream_get_line() 而不是fread()。它几乎相同,只是它允许您指定任何您希望的结束分隔符。请注意,它确实将分隔符作为读取的一部分返回。

$contents = stream_get_line($fp,1000,".");

【讨论】:

  • 谢谢,但是只能在句号后拆分吗?
  • 我尝试使用 20000 作为长度的 stream_get_line,并使用了古腾堡网站上的一个大文本文件 - gutenberg.org/files/2759/2759.txt。创建了超过一千个几乎没有文本的文件。
  • 我认为问题在于它停止读取字符数或分隔符,以先到者为准。问题是句号总是第一位的。所以文件最终很短。相反,它应该在到达分隔符之前加上长度。
  • 如果这就是你想要做的,那么你应该做一个初始的freads($fp,1000),然后跟着它stream_get_line()。在您不必担心寻找结束分隔符之前,您将获得完整的文本块。
  • 这将如何工作?我尝试了以下输出相同的小文件。 $contents = fread($fp,1000); $contents = stream_get_line($contents,1000,".");
【解决方案2】:

运行函数有错误;变量$split 未定义。

【讨论】:

    【解决方案3】:

    最简单的方法是读取文件的内容,拆分内容,然后保存到另外两个文件中。如果您的文件超过几 GB,由于整数大小的限制,您将在 PHP 中遇到问题。

    【讨论】:

    • 假设文件很大,在循环中简单地读取所需的字节数比一次读取整个原始文件要高效得多。除非您正在读取大于整数最大值的文件块,否则您也不会遇到大小问题。
    • 我应该更具体一点,文本文件的大小不会超过 10-15MB。
    • @zombat,PHP 无法使文件读取指针超过 4,294,967,296 字节.. 所以如果您的文件超过 4GB,即使您分块读取它,一旦达到 4GB,PHP 也会崩溃标记。
    • @Ian - 最大整数大小由 PHP_INT_MAX 定义,这是一个基于操作系统的常量集,所以是的,你不能在 32 位系统上使用比它更大的任何东西。在这种情况下,您必须使用解决方法。
    【解决方案4】:

    你也可以编写一个类来为你做这件事。

    <?php
    
    /**
    * filesplit class : Split big text files in multiple files
    *
    * @package
    * @author Ben Yacoub Hatem <hatem@php.net>
    * @copyright Copyright (c) 2004
    * @version $Id$ - 29/05/2004 09:02:10 - filesplit.class.php
    * @access public
    **/
    class filesplit{
        /**
         * Constructor
         * @access protected
         */
        function filesplit(){
    
        }
    
        /**
         * File to split
         * @access private
         * @var string
         **/
        var $_source = 'logs.txt';
    
        /**
         *
         * @access public
         * @return string
         **/
        function Getsource(){
            return $this->_source;
        }
    
        /**
         *
         * @access public
         * @return void
         **/
        function Setsource($newValue){
            $this->_source = $newValue;
        }
    
        /**
         * how much lines per file
         * @access private
         * @var integer
         **/
        var $_lines = 1000;
    
        /**
         *
         * @access public
         * @return integer
         **/
        function Getlines(){
            return $this->_lines;
        }
    
        /**
         *
         * @access public
         * @return void
         **/
        function Setlines($newValue){
            $this->_lines = $newValue;
        }
    
        /**
         * Folder to create splitted files with trail slash at end
         * @access private
         * @var string
         **/
        var $_path = 'logs/';
    
        /**
         *
         * @access public
         * @return string
         **/
        function Getpath(){
            return $this->_path;
        }
    
        /**
         *
         * @access public
         * @return void
         **/
        function Setpath($newValue){
            $this->_path = $newValue;
        }
    
        /**
         * Configure the class
         * @access public
         * @return void
         **/
        function configure($source = "",$path = "",$lines = ""){
            if ($source != "") {
                $this->Setsource($source);
            }
            if ($path!="") {
                $this->Setpath($path);
            }
            if ($lines!="") {
                $this->Setlines($lines);
            }
        }
    
    
        /**
         *
         * @access public
         * @return void
         **/
        function run(){
            $i=0;
            $j=1;
            $date = date("m-d-y");
            unset($buffer);
    
            $handle = @fopen ($this->Getsource(), "r");
            while (!feof ($handle)) {
              $buffer .= @fgets($handle, 4096);
              $i++;
                  if ($i >= $split) {
                  $fname = $this->Getpath()."part.$date.$j.txt";
                   if (!$fhandle = @fopen($fname, 'w')) {
                        print "Cannot open file ($fname)";
                        exit;
                   }
    
                   if (!@fwrite($fhandle, $buffer)) {
                       print "Cannot write to file ($fname)";
                       exit;
                   }
                   fclose($fhandle);
                   $j++;
                   unset($buffer,$i);
                    }
            }
            fclose ($handle);
        }
    
    
    }
    ?>
    
    
    Usage Example
    <?php
    /**
    * Sample usage of the filesplit class
    *
    * @package filesplit
    * @author Ben Yacoub Hatem <hatem@php.net>
    * @copyright Copyright (c) 2004
    * @version $Id$ - 29/05/2004 09:14:06 - usage.php
    * @access public
    **/
    
    require_once("filesplit.class.php");
    
    $s = new filesplit;
    
    /*
    $s->Setsource("logs.txt");
    $s->Setpath("logs/");
    $s->Setlines(100); //number of lines that each new file will have after the split.
    */
    
    $s->configure("logs.txt", "logs/", 2000);
    $s->run();
    ?>
    

    来源http://www.weberdev.com/get_example-3894.html

    【讨论】:

    • 这正是我所需要的,非常有用,但是我遇到了一个问题,无论我设置什么,它都会将我的源文件的每一行放入一个单独的文件中。所以一个 500 行的文件会创建 500 个文件
    • 请在我的回答中查看以下修改后的代码。如果您在 run() 函数中进行编辑,它现在将正常工作。抱歉,这是 4 年后的事了,但希望它能帮助到这个页面的人。
    【解决方案5】:

    我已经修复了课程并且可以完美地使用 .txt 文件。

    <?php
    
    /**
    * filesplit class : Split big text files in multiple files
    *
    * @package
    * @author Ben Yacoub Hatem <hatem@php.net>
    * @copyright Copyright (c) 2004
    * @version $Id$ - 29/05/2004 09:02:10 - filesplit.class.php
    * @access public
    **/
    class filesplit{
        /**
         * Constructor
         * @access protected
         */
        function filesplit(){
    
        }
    
        /**
         * File to split
         * @access private
         * @var string
         **/
        var $_source = 'logs.txt';
    
        /**
         *
         * @access public
         * @return string
         **/
        function Getsource(){
            return $this->_source;
        }
    
        /**
         *
         * @access public
         * @return void
         **/
        function Setsource($newValue){
            $this->_source = $newValue;
        }
    
        /**
         * how much lines per file
         * @access private
         * @var integer
         **/
        var $_lines = 1000;
    
        /**
         *
         * @access public
         * @return integer
         **/
        function Getlines(){
            return $this->_lines;
        }
    
        /**
         *
         * @access public
         * @return void
         **/
        function Setlines($newValue){
            $this->_lines = $newValue;
        }
    
        /**
         * Folder to create splitted files with trail slash at end
         * @access private
         * @var string
         **/
        var $_path = 'logs/';
    
        /**
         *
         * @access public
         * @return string
         **/
        function Getpath(){
            return $this->_path;
        }
    
        /**
         *
         * @access public
         * @return void
         **/
        function Setpath($newValue){
            $this->_path = $newValue;
        }
    
        /**
         * Configure the class
         * @access public
         * @return void
         **/
        function configure($source = "",$path = "",$lines = ""){
            if ($source != "") {
                $this->Setsource($source);
            }
            if ($path!="") {
                $this->Setpath($path);
            }
            if ($lines!="") {
                $this->Setlines($lines);
            }
        }
    
    
        /**
         *
         * @access public
         * @return void
         **/
        function run(){
    
            $buffer = '';
            $i=0;
            $j=1;
            $date = date("m-d-y");
            $handle = @fopen ($this->Getsource(), "r");
    
            while (!feof ($handle)) {
    
                $buffer .= @fgets($handle, 4096);
                $i++;
    
                if ($i >= $this->getLines()) { 
    
                    // set your filename pattern here.
                    $fname = $this->Getpath()."split_{$j}.txt";
    
                    if (!$fhandle = @fopen($fname, 'w')) {
                        print "Cannot open file ($fname)";
                        exit;
                    }
    
                    if (!@fwrite($fhandle, $buffer)) {
                        print "Cannot write to file ($fname)";
                        exit;
                    }
                    fclose($fhandle);
                    $j++;
                    unset($buffer,$i);
                }
            } 
            if ( !empty($buffer) && !empty($i) ) {
                $fname = $this->Getpath()."split_{$j}.txt";
    
                if (!$fhandle = @fopen($fname, 'w')) {
                    print "Cannot open file ($fname)";
                    exit;
                }
    
                if (!@fwrite($fhandle, $buffer)) {
                    print "Cannot write to file ($fname)";
                    exit;
                }
                    fclose($fhandle);
                unset($buffer,$i);  
            }
            fclose ($handle);
        }
    
    
    }
    ?>
    

    使用示例

    <?php
    
    require_once("filesplit.class.php");
    
    $s = new filesplit;
    $s->Setsource("logs.txt");
    $s->Setpath("logs/");
    $s->Setlines(100); //number of lines that each new file will have after the split.
    //$s->configure("logs.txt", "logs/", 2000);
    $s->run();
    ?>
    

    【讨论】:

      【解决方案6】:

      在run函数中,我做了如下调整,修复了“split is not defined”的警告。

      function run(){
      
              $buffer='';
              $i=0;
              $j=1;
              $date = date("m-d-y");
              $handle = @fopen ($this->Getsource(), "r");
      
              while (!feof ($handle)) {
      
                  $buffer .= @fgets($handle, 4096);
                  $i++;
      
                  if ($i >= $this->getLines()) { // $split was here, empty value..
      
                      // set your filename pattern here.
                      $fname = $this->Getpath()."dma_map_$date.$j.csv";
      
                      if (!$fhandle = @fopen($fname, 'w')) {
                          print "Cannot open file ($fname)";
                          exit;
                      }
      
                      if (!@fwrite($fhandle, $buffer)) {
                          print "Cannot write to file ($fname)";
                          exit;
                      }
                      fclose($fhandle);
                      $j++;
                      unset($buffer,$i);
                  }
              }
              fclose ($handle);
          }
      

      我使用这个类将一个 500,000 行的 CSV 文件拆分为 10 个文件,因此 phpmyadmin 可以使用它而不会出现超时问题。像魅力一样工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多