csv PHP数组不打印数组的第一个元素的问题[重复]

vi4fp9gy  于 2023-06-03  发布在  PHP
关注(0)|答案(1)|浏览(133)

此问题已在此处有答案

Remove BOM () from imported .csv file(7个回答)
How do I remove  from the beginning of a file?(23个回答)
How do I read a UTF CSV file in PHP with a BOM?(1个答案)
How to remove multiple UTF-8 BOM sequences(12个回答)
preg_replace UTF-8 BOM Unicode character(1个答案)
13小时前关闭
我有一个问题,我似乎无法解决。我有一个函数,它接受一个文件并将其转换为一个数组,使用第一行作为键:

function parseCSVToArray($filePath)
{
    $csvData = [];

    if (($handle = fopen($filePath, "r")) !== false) {
        $keys = fgetcsv($handle); // Get the first row as keys

        while (($data = fgetcsv($handle)) !== false) {
            $rowData = array();
            foreach ($keys as $index => $key) {
                $rowData[$key] = $data[$index] ?? ''; // Assign each value to its corresponding key
            }
            $csvData[] = $rowData;
        }

        fclose($handle);
    }
    return $csvData;
}

一切正常,并按预期创建阵列:

$getTheRecords = parseCSVToArray('Data/records.csv');

// File contents
record,subdomain,hub_knows,domain,type,value,action,rationale
mail.sub.domain.com.,sub.domain.com,Hub knows about this,domain.com,CNAME,dispatch.domain.com.,DELETE,Dispatch links can go
Array
(
    [record] => mail.sub.domain.com
    [subdomain] => sub.domain.com
    [hub_knows] => Hub knows about this
    [domain] => domain.com
    [type] => CNAME
    [value] => dispatch.domain.com.
    [action] => DELETE
    [rationale] => Dispatch links can go
)

现在的问题是我什么时候去使用或打印数据。当我循环遍历数组时,使用:

foreach($getTheRecords as $element)
{
    echo "<div style='margin-bottom: 20px'>";
    echo($element['subdomain']); // This will print the subdomain as expected.
    echo "</div>";
}

如果我将'subdomain'更改为'record',则不会打印任何内容。但是,每隔一个“键”就可以打印结果。
提前感谢您的帮助!
我试过把第一个键的名字改成“mainrecord”或其他什么,它仍然不会打印出来。
Iside循环var_dmup():

array(8) {
  ["record"]=>
  string(31) "mail.0lemonade.starchapter.com."
  ["subdomain"]=>
  string(25) "0lemonade.starchapter.com"
  ["hub_knows"]=>
  string(20) "Hub knows about this"
  ["domain"]=>
  string(17) "scdomaintest3.com"
  ["type"]=>
  string(5) "CNAME"
  ["value"]=>
  string(22) "dispatch.scnetops.com."
  ["action"]=>
  string(6) "DELETE"
  ["rationale"]=>
  string(21) "Dispatch links can go"
}
wqsoz72f

wqsoz72f1#

您的文件可能在开始时有一个UTF8字节顺序标记[BOM],它会抛出第一个键。虽然对于UTF8来说BOM根本不是必需的,但是一些程序仍然添加它作为文件是UTF8的“提示”。
如果你输入var_dump($keys[0], bin2hex($keys[0]),你可能会看到第一个键的长度比可见的要长,十六进制输出将显示它的前缀为EFBBBF,这是BOM。
尝试替换:

$keys = fgetcsv($handle);

有:

$keys = str_getcsv(preg_replace("/^\xef\xbb\xbf/", "", fgets($handle)));

这将修剪BOM(如果存在)。

**编辑:**适用范围更广的代码。

function stream_skip_bom($stream_handle) {
    if( ! stream_get_meta_data($stream_handle)['seekable'] ) {
        throw new \Exception('Specified stream is not seekable, and cannot be rewound.');
    }
    
    $pos = ftell($stream_handle);
    $test = fread($stream_handle, 3);
    
    if( $test !== "\xef\xbb\xbf" ) {
        fseek($stream_handle, $pos);
    }
}

所以在打开$handle之后,你可以简单地调用:

stream_skip_bom($handle);

相关问题