Büyük bir CSV dosyası ile ilgili sorun

7 Cevap

Ben çok büyük bir CSV dosyası var. 51427 çizgileri kesin olmalıdır.

Ben sadece bir diziye gerekli satırları okuyabilirsiniz bir yolu var, değil mi? Bu işler daha hızlı olacaktır.

7 Cevap

Sen csv dosya aktarımı bakmak isteyebilirsiniz. Başlangıç ​​dosyası konumu gönderin, bir ProgressiveReader.php için paramters almak gibi okumak için pozisyon ve bayt sayısını başlangıç

class NoFileFoundException extends Exception {
    function __toString() {
        return '<h1><b>ERROR:</b> could not find ('
                    .$this->getMessage().
                    ') please check your settings.</h1>';
    }
}

class NoFileOpenException extends Exception {
    function __toString() {
        return '<h1><b>ERROR:</b> could not open ('
                    .$this->getMessage().
                    ') please check your settings.</h1>';
    }
}

interface Reader {
    function setFileName($fName);
    function open();
    function setBufferOffset($offset);
    function bufferSize();
    function isOffset();
    function setPacketSize($size);
    function read();
    function isEOF();
    function close();
    function readAll();
}

class ProgressiveReader implements Reader {
    private $fName;
    private $fileHandler;
    private $offset = 0;
    private $packetSize = 0;

    public function setFileName($fName) {
        $this->fName = $fName;
        if(!file_exists($this->fName)) {
            throw new NoFileFoundException($this->fName);
        }
    }

    public function open() {
        try {
            $this->fileHandler = fopen($this->fName, 'rb');
        }
        catch (Exception $e) {
            throw new NoFileOpenException($this->fName);
        }
        fseek($this->fileHandler, $this->offset);
    }

    public function setBufferOffset($offset) {
        $this->offset = $offset;
    }

    public function bufferSize() {
        return filesize($this->fName) - (($this->offset > 0) ? ($this->offset  + 1) : 0);
    }

    public function isOffset() {
        if($this->offset === 0) {
            return false;
        }
        return true;
    }

    public function setPacketSize($size) {
        $this->packetSize = $size;
    }

    public function read() {
        return fread($this->fileHandler, $this->packetSize);
    }

    public function isEOF() {
        return feof($this->fileHandler);
    }

    public function close() {
        if($this->fileHandler) {
            fclose($this->fileHandler);
        }
    }

    public function readAll() {
        return fread($this->fileHandler, filesize($this->fName));
    }
}

Burada birim testler şunlardır:

require_once 'PHPUnit/Framework.php';

require_once dirname(__FILE__).'/../ProgressiveReader.php';

class ProgressiveReaderTest extends PHPUnit_Framework_TestCase {

    protected $reader;
    private $fp;
    private $fname = "Test.txt";

    protected function setUp() {
        $this->createTestFile();
        $this->reader = new ProgressiveReader();
    }

    protected function tearDown() {
        $this->reader->close();
    }

    public function test_isValidFile() {
        $this->reader->setFileName($this->fname);
    }

    public function test_isNotValidFile() {
        try {
            $this->reader->setFileName("nothing.tada");
        }
        catch (Exception $e) {
            return;
        }

        $this->fail();
    }

    public function test_isFileOpen() {
        $this->reader->setFileName($this->fname);
        $this->reader->open();
    }

    public function test_couldNotOpenFile() {
        $this->reader->setFileName($this->fname);
        try {
            $this->deleteTestFile();
            $this->reader->open();
        }
        catch (Exception $e) {
            return;
        }

        $this->fail();
    }

    public function test_bufferSizeZeroOffset() {
        $this->reader->setFileName($this->fname);
        $this->reader->open();
        $this->assertEquals($this->reader->bufferSize(), 12);
    }

    public function test_bufferSizeTwoOffset() {
        $this->reader->setFileName($this->fname);
        $this->reader->setBufferOffset(2);
        $this->reader->open();
        $this->assertEquals($this->reader->bufferSize(), 9);
    }

    public function test_readBuffer() {
        $this->reader->setFileName($this->fname);
        $this->reader->setBufferOffset(0);
        $this->reader->setPacketSize(1);
        $this->reader->open();
        $this->assertEquals($this->reader->read(), "T");
    }

    public function test_readBufferWithOffset() {
        $this->reader->setFileName($this->fname);
        $this->reader->setBufferOffset(2);
        $this->reader->setPacketSize(1);
        $this->reader->open();
        $this->assertEquals($this->reader->read(), "S");
    }

    public function test_readSuccesive() {
        $this->reader->setFileName($this->fname);
        $this->reader->setBufferOffset(0);
        $this->reader->setPacketSize(6);
        $this->reader->open();
        $this->assertEquals($this->reader->read(), "TEST1\n");
        $this->assertEquals($this->reader->read(), "TEST2\n");
    }

    public function test_readEntireBuffer() {
        $this->reader->setFileName($this->fname);
        $this->reader->open();
        $this->assertEquals($this->reader->readAll(), "TEST1\nTEST2\n");
    }

    public function test_isNotEOF() {
        $this->reader->setFileName($this->fname);
        $this->reader->setBufferOffset(2);
        $this->reader->setPacketSize(1);
        $this->reader->open();
        $this->assertFalse($this->reader->isEOF());
    }

    public function test_isEOF() {
        $this->reader->setFileName($this->fname);
        $this->reader->setBufferOffset(0);
        $this->reader->setPacketSize(15);
        $this->reader->open();
        $this->reader->read();
        $this->assertTrue($this->reader->isEOF());
    }

    public function test_isOffset() {
        $this->reader->setFileName($this->fname);
        $this->reader->setBufferOffset(2);
        $this->assertTrue($this->reader->isOffset());
    }

    public function test_isNotOffset() {
        $this->reader->setFileName($this->fname);
        $this->assertFalse($this->reader->isOffset());
    }

    private function createTestFile() {
        $this->fp = fopen($this->fname, "wb");
        fwrite($this->fp, "TEST1\n");
        fwrite($this->fp, "TEST2\n");
        flush();
        fclose($this->fp);
    }

    private function deleteTestFile() {
        if(file_exists($this->fname)) {
            unlink($this->fname);
        }

    }
}

Doğrudan veritabanı sunucusuna bağlayabilir miyim?

Eğer öyleyse, ben senin csv almak için SQLyog gibi bir 3. parti programı kullanarak düşünün.

Ayrıca dosya upload ve doğrudan bu veri almak için mysql kabuk kullanabilirsiniz:

LOAD DATA INFILE '/path/to/your_file.csv' INTO TABLE table_name FIELDS TERMINATED BY ',';

Bu bir diziye bütün CSV dosyasını okur

50000 + bütün satırları?

Hat (fgets ()) tarafından satır okuyarak PHP dosyasının aranan bloğunun başlangıcında ilerlemek ve ardından diziye her (gerekli) satırı ekleyin; Eğer fgetcsv () ile hattın dizi alabilirsiniz.

edit: Ben tam ayrıntılarını bilmiyorum, ama ben bir veri yapısı içine her şeyi okuyarak sadece ne gerek okuma yolu daha fazla maliyeti olduğunu seziyorum.

Script muhtemelen çok uzun sürüyor ve sona alır.

Php.ini de max_execution_time yönergesi bakmak ve size uygun bir şey olarak ayarlamanız gerekir.

Varsayılan max_execution_time 30 saniyeye ayarlanmıştır, böylece komut muhtemelen sona alır.

Zaman içinde de sınırlı olması gereken komut varsa, siz) set_time_init (çağırarak ayrı ayrı yapabilirsiniz;

Eğer mysql içine CSV alma için (eğer linux üzerinde iseniz) bash / kabuğunu kullanarak denediniz mi? Sanırım bu dosyayı aktarmak php (veya herhangi bir web uygulaması) yerine kullanmanız gereken ne düşünüyorum da, yakut veya Perl ya da etajer kullanabilirsiniz.

Ben hızlı MySQL LOAD DATA INFILE komutunu kullanmanızı öneririm:

http://dev.mysql.com/doc/refman/5.1/en/load-data.html

Bu bir seçenek değil ise, (bir kabuk erişimi varsayarak) CSV dosyasını bölünmüş olabilir.

Bah! Bu cevabı görmezden. Bir yinelenen oldu. Yukarıda fgetcsv arasında Scorchio ait söz () Bkz.