PHP中的str_getcsv函数处理数组问题

9
我正在上传一个CSV文件,并使用str_getcsv解析它。所有操作都很好,除了我需要一种遍历的方法。理想情况下,希望数组返回并长成这样:
Array (      
    [1] => Array
       (
            [0] => 1 // first id in csv
            [1] => name
            [2] => address
            [3] => town
            [4] => state
            [5] => zip
            [6] => phone
            [7] => website
            [8] => other
            [9] => other
        )
    [22] => Array
       (
            [10] => name
            [11] => address
            [12] => town
            [13] => state
            [14] => zip
            [15] => phone
            [16] => website
            [17] => other
            [18] => other
        )
    [24] => Array
       (
            [19] => name
            [20] => address
            [21] => town
            [22] => state
            [23] => zip
            [24] => phone
            [25] => website
            [26] => other
            [27] => other
        )
)

然而,数据返回的格式如下:
Array
(
    [0] => 1 // first id in csv
    [1] => name
    [2] => address
    [3] => town
    [4] => state
    [5] => zip
    [6] => phone
    [7] => website
    [8] => other
    [9] => other
22 // id field
    [10] => name
    [11] => address
    [12] => town
    [13] => state
    [14] => zip
    [15] => phone
    [16] => website
    [17] => other
    [18] => other
24// id field
    [19] => name
    [20] => address
    [21] => town
    [22] => state
    [23] => zip
    [24] => phone
    [25] => website
    [26] => other
    [27] => other

有没有关于如何修复这个问题,使其看起来像上面的数组的建议? 现在我正在做:
$csvfile = file_get_contents($targetFile);
$csv = str_getcsv($csvfile);

可能是 PHP CSV 字符串转数组 的重复问题。 - user
我将此标记为重复,尽管这个问题比那个问题早,但那个问题更受欢迎。 - user
3个回答

17

str_getcsv() 函数期望传入的字符串参数是 一个 记录。
但由于你的数据源本来就是一个文件,所以最简单的方法可能是使用 fgetcsv() 而不是 str_getcsv()。

$data = array();
$fp = fopen($targetFile, 'rb');
while(!feof($fp)) {
    $data[] = fgetcsv($fp);
}
fclose($fp);
自包含示例:
<?php
$targetFile = 'soTest.csv';
setup($targetFile);

$data = array();
$fp = fopen($targetFile, 'rb');
while(!feof($fp)) {
    $data[] = fgetcsv($fp);
}
var_dump($data);


function setup($targetFile) {
    file_put_contents($targetFile, <<< eot
1,name,address,town,state,zip,phone,website,other,other
2,name,address,town,state,zip,phone,website,other,other
3,name,address,town,state,zip,phone,website,other,other
eot
    );
}

打印

array(3) {
  [0]=>
  array(10) {
    [0]=>
    string(1) "1"
    [1]=>
    string(4) "name"
    [2]=>
    string(7) "address"
    [3]=>
    string(4) "town"
    [4]=>
    string(5) "state"
    [5]=>
    string(3) "zip"
    [6]=>
    string(5) "phone"
    [7]=>
    string(7) "website"
    [8]=>
    string(5) "other"
    [9]=>
    string(5) "other"
  }
  [1]=>
  array(10) {
    [0]=>
    string(1) "2"
    [1]=>
    string(4) "name"
    [2]=>
    string(7) "address"
    [3]=>
    string(4) "town"
    [4]=>
    string(5) "state"
    [5]=>
    string(3) "zip"
    [6]=>
    string(5) "phone"
    [7]=>
    string(7) "website"
    [8]=>
    string(5) "other"
    [9]=>
    string(5) "other"
  }
  [2]=>
  array(10) {
    [0]=>
    string(1) "3"
    [1]=>
    string(4) "name"
    [2]=>
    string(7) "address"
    [3]=>
    string(4) "town"
    [4]=>
    string(5) "state"
    [5]=>
    string(3) "zip"
    [6]=>
    string(5) "phone"
    [7]=>
    string(7) "website"
    [8]=>
    string(5) "other"
    [9]=>
    string(5) "other"
  }
}
编辑2:如果要将每个记录的第一个元素用作结果数组中的键:
<?php
$targetFile = 'soTest.csv';
setup($targetFile);

$data = array();
$fp = fopen($targetFile, 'rb');
while(!feof($fp)) {
    $row = fgetcsv($fp);
    $id = array_shift($row);
    $data[$id] = $row;
}
var_dump($data);


function setup($targetFile) {
    file_put_contents($targetFile, <<< eot
1,name,address,town,state,zip,phone,website,other,other
2,name,address,town,state,zip,phone,website,other,other
3,name,address,town,state,zip,phone,website,other,other
eot
    );
}

这仍然返回相同的内容。我需要它看起来像问题顶部的数组。 - Drew Bartlett
@Drew:也许你的问题是PHP无法检测文件中的行尾。请参阅http://docs.php.net/filesystem.configuration#ini.auto-detect-line-endings。 - VolkerK
1
我建议你再次检查你的csv文件,确保每条记录之间没有用逗号分隔。虽然我还没有运行这段代码,但它看起来很不错,应该会得到你想要的数组。哦,对了,每条记录也应该在新的一行上。 - mseancole

0

这不是世界上最漂亮的东西,但我认为它有效。

//make the arrays needed
$csvtmp = array();
$csvFinal = array();

$csvfile = file_get_contents('test.csv');
$csv = str_getcsv($csvfile,"\n"); //make an array element for every record (new line)

//Loop through the result 
foreach ($csv as $key => $item) 
{
    array_push($csvtmp, str_getcsv($item,";")); //push each record to the csv temp array

    //here's the messy part. This set the key of the csvFinal array to the first field in the current record and for the value it gives it the array we got from the previous str_getcsv.
    $csvFinal[$csvtmp[$key][0]] = $csvtmp[$key]; 
    //Here we just unset the id row in the final array
    unset($csvFinal[$csvtmp[$key][0]][0]);

}

echo "<pre>";
    print_r($csvFinal);
echo "</pre>"; 

代码的结果:

Array
(
    [22] => Array
        (
            [1] => name1
            [2] => address1
            [3] => town1
            [4] => state1
            [5] => zip1
            [6] => phone1
            [7] => website1
            [8] => other1
            [9] => other1
        )

    [23] => Array
        (
            [1] => name2
            [2] => address2
            [3] => town2
            [4] => state2
            [5] => zip2
            [6] => phone2
            [7] => website2
            [8] => other1
            [9] => other1
        )

    [24] => Array
        (
            [1] => name3
            [2] => address3
            [3] => town3
            [4] => state3
            [5] => zip3
            [6] => phone3
            [7] => website3
            [8] => other1
            [9] => other1
        )
}

希望这能有所帮助。

1
不应该使用\n来确定CSV中的新行,因为如果任何列行中有多行,则\n会导致格式错误。 - Solomon Closson

0

嗯,只需要计算一个条目有多少项,然后在一个循环内再嵌套一个循环

// loop on all items; $i+=$ITEM_SIZE go to the next item each outer loop
// (10 elements for ITEM in Opening Post's case)

// this for loops between all items
for ($i=0;$i<=$ARRAY_LENGHT;$i+=10)
{
    // this for loops between each item's elements
    for($c=1; $c<=10;$c++)
    {
        switch($c)
        {
            case 1:
              $id = $array[$i+$c];
              break;

            case 2:
              $name = $array[$i+$c];
              break;

            case 3:
              $address = $array[$i+$c];
              break;

            //etc to 10th element:

            case 10:
              $other = $array[$i+$c];
              break;

        }
    }

    // When the item is all done use the item
    // it as you need, example:

    echo "id: {$id}\nname: {$name}\naddress: {$adress}"; //etc

    // then unset($id,$name,$address, $etc);
    // for the next iteration of loop (next item)
}

这就是我刚刚做的,而且效果非常好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接