powered by nequal
Home » CSV_Iterator » Timeline » 1055

Changeset 1055 -- 2009-08-04 18:08:56

Author
MugeSo
Comment
値行が1行だけで、しかもファイル末尾に改行コードがない時におかしくなるバグを修正

Diffs

CSV_Iterator/trunk/tests/src/CSV/CSV_IteratorTest.php

@@ -21,26 +21,15 @@
}
/**
-     * @todo Implement testRewind().
+     * @dataProvider constructData
*/
-    public function testRewind() {
-    // Remove the following lines when you implement this test.
-        $this->markTestIncomplete(
-            'This test has not been implemented yet.'
-        );
+    public function testRewind($file, $encoding, $delimiter, $enclosure, $expected) {
+        $obj = new CSV_Iterator(realpath(dirname(__FILE__) . '/../../fixtures/' . $file), $encoding, $delimiter, $enclosure);
+        $obj->rewind();
+        $this->assertEquals(current($expected), $obj->current());
}
/**
-     * @todo Implement testNext().
-     */
-    public function testNext() {
-    // Remove the following lines when you implement this test.
-        $this->markTestIncomplete(
-            'This test has not been implemented yet.'
-        );
-    }
-
-    /**
* @dataProvider constructData
*/
public function testCurrent($file, $encoding, $delimiter, $enclosure, $expected) {
@@ -49,26 +38,6 @@
}
/**
-     * @todo Implement testKey().
-     */
-    public function testKey() {
-    // Remove the following lines when you implement this test.
-        $this->markTestIncomplete(
-            'This test has not been implemented yet.'
-        );
-    }
-
-    /**
-     * @todo Implement testValid().
-     */
-    public function testValid() {
-    // Remove the following lines when you implement this test.
-        $this->markTestIncomplete(
-            'This test has not been implemented yet.'
-        );
-    }
-
-    /**
* @todo Implement testSetRowLength().
*/
public function testSetRowLength() {
@@ -139,7 +108,6 @@
)),
array('withHeaderWithoutEOLatEOF.csv', 'ascii', ',', '"', array(
array('header1'=>'value1', 'header2'=>'value2'),
-                    array('header1'=>'value3', 'header2'=>'value4'),
)),
);
}

CSV_Iterator/trunk/tests/fixtures/withHeaderWithoutEOLatEOF.csv

@@ -1,3 +1,2 @@
header1,header2
-value1,value2
-value3,value4
\ ファイルの末尾に改行がありません
+value1,value2
\ ファイルの末尾に改行がありません

CSV_Iterator/trunk/src/CSV/Iterator.php

@@ -30,7 +30,7 @@
$this->enclosure = mb_convert_encoding($enclosure, 'utf-8');
$this->setRowLength($rowlength);
-        $this->filePointer = fopen($file, 'r');
+        $this->filePointer = fopen($file, 'rb');
$this->_setEncoding($encoding);
$this->setOutputEncoding($outputEncoding);
@@ -42,19 +42,18 @@
public function rewind()
{
fseek($this->filePointer, $this->offset);
+        $this->rowCounter = -1;
$this->next();
-        $this->rowCounter = 0;
}
public function next()
{
-
+        ++$this->rowCounter;
$data = $this->readRow();
if($data!==null && count($data)!==count($this->header)) {
-            throw new RuntimeException('CSV parse error. Number of columns is not equal to number of header.');
+            throw new RuntimeException('CSV parse error. Number of columns is not equal to number of header at row #'.  $this->rowCounter .'.' . var_export(array($data, $this->header), true));
}
$this->currentRow = $data ? array_combine($this->header, $data) : null;
-        ++$this->rowCounter;
}
public function current()
@@ -96,10 +95,10 @@
// また、マルチバイト関係で安全に処理するために、文字エンコーディングを一旦UTF-8にする
while (!feof($this->filePointer)) {
//            $line .= mb_convert_encoding(call_user_func_array('fgets', $arg), 'utf-8', $this->encoding);
-            $line .= mb_convert_encoding(call_user_func_array('stream_get_line', $arg), 'utf-8', $this->encoding);
+//            $line .= mb_convert_encoding(call_user_func_array('stream_get_line', $arg), 'utf-8', $this->encoding);
+            $line .= mb_convert_encoding(self::getLine($this->filePointer, $this->rowLength, $this->eol), 'utf-8', $this->encoding);
$itemcnt = preg_match_all('/'.$e.'/u', $line, $dummy);
if ($itemcnt % 2 == 0) break;
-            $line .= "\xd\xa";
}
$csv_line = preg_replace('/(?:\r\n|[\r\n])?$/u', $d, trim($line));
@@ -159,5 +158,33 @@
{
$this->outputEncoding = strtoupper($encoding)==='UTF-8' ? null : $encoding;
}
+
+    /**
+     * stream_get_lineにバグがあるため仕方なく作った
+     *
+     * @see http://bugs.php.net/bug.php?id=49148
+     * @param resource $fp ファイルポインタ
+     * @param int $buf_size 最大サイズ
+     * @param string $eol 行区切り
+     * @return string 1行分の文字
+     */
+    static public function getLine($fp, $buf_size, $eol)
+    {
+        $ret = '';
+        $eol_len = strlen($eol);
+        $eol_pos = 0;
+        if(!$buf_size) $buf_size = PHP_INT_MAX;
+        while(($c = fgetc($fp))!==false && strlen($ret) < $buf_size) {
+            $ret .= $c;
+            if($c === $eol[$eol_pos]) {
+                if(++$eol_pos === $eol_len) {
+                    break;
+                }
+                continue;
+            }
+            $eol_pos = 0;
+        }
+        return $ret;
+    }
}
?>