28

フィールド名を含む最初の行を持つ CSV があります。例のデータは...

"Make","Model","Note"
"Chevy","1500","loaded"
"Chevy","2500",""
"Chevy","","loaded"

キー名が列見出しであるキーと値のペアの配列でフォーマットされたデータが必要です。行1では次のようになると思います:

$array = [
    "Make" => "Chevy",
    "Model" => "1500",
    "Note" => "loaded"
];

...行 2...

$array = [
    "Make" => "Chevy",
    "Model" => "1500",
    "Note" => ""
];

...そして3行目...

$array = [
    "Make" => "Chevy",
    "Model" => "",
    "Note" => "loaded"
];

静的以外にこれを行う方法がわかりません-問題は、関連付けられたデータを含む列が、あるファイルから次のファイルに変更される可能性があることです...列が再配置、削除、または追加されます。

あなたのアイデアは大歓迎です。

4

9 に答える 9

64
$all_rows = array();
$header = fgetcsv($file);
while ($row = fgetcsv($file)) {
  $all_rows[] = array_combine($header, $row);
}
print_r($all_rows);
于 2012-04-16T20:21:27.163 に答える
36

PHP は 内で必要なものの 99.9% をすでに提供していますSplFileObject。不足している 0.1% を拡張して追加します。次の例CSVFileでは、それを拡張しています。

$csv = new CSVFile('../data/test.csv');

foreach ($csv as $line)
{
    var_dump($line);
}

あなたのサンプルデータで:

array(3) {
  ["Make"]=>  string(5) "Chevy"
  ["Model"]=> string(4) "1500"
  ["Note"]=>  string(6) "loaded"
}
array(3) {
  ["Make"]=>  string(5) "Chevy"
  ["Model"]=> string(4) "2500"
  ["Note"]=> string(0) ""
}
array(3) {
  ["Make"]=>  string(5) "Chevy"
  ["Model"]=> string(0) ""
  ["Note"]=>  string(6) "loaded"
}

CSVFileは次のように定義されます。

class CSVFile extends SplFileObject
{
    private $keys;

    public function __construct($file)
    {
        parent::__construct($file);
        $this->setFlags(SplFileObject::READ_CSV);
    }

    public function rewind()
    {
        parent::rewind();
        $this->keys = parent::current();
        parent::next();
    }

    public function current()
    {
        return array_combine($this->keys, parent::current());
    }

    public function getKeys()
    {
        return $this->keys;
    }
}

このようにすると、詳細がうまくカプセル化されます。さらに、関数内でエラー (カウントの不一致など) を処理するのがより簡単にcurrent()なるため、データを使用するコードはそれを処理する必要がありません。

編集:

ただし、与えられた例は、再利用性の点で短いものです。SplFileObjectから拡張する代わりに、それを集約する方がはるかに優れています。

class KeyedArrayIterator extends IteratorIterator
{
    private $keys;

    public function rewind()
    {
        parent::rewind();
        $this->keys = parent::current();
        parent::next();
    }

    public function current()
    {
        return array_combine($this->keys, parent::current());
    }

    public function getKeys()
    {
        return $this->keys;
    }
}

コードは同じですが、コンストラクターにカプセル化された詳細は省略されています。この縮小により、型をより広く使用することができます。たとえば、前述のSplFileObjectと一緒に (ただし、それだけでなく) :

$file = new SplFileObject('../data/test.csv');
$file->setFlags($file::READ_CSV);

$csv = new KeyedArrayIterator($file);

foreach ($csv as $line) {
    var_dump($line);
}

これが冗長すぎるように聞こえる場合は、もう一度ラップして、より良いファサードを与えることができます。

class CSVFile extends KeyedArrayIterator
{
    /**
     * @param string $file
     */
    public function __construct($file)
    {
        parent::__construct(new SplFileObject($file));
        $this->setFlags(SplFileObject::READ_CSV);
    }
}

TraversableIteratorの標準的な装飾機能のおかげで、 CSVFileの最初の例の元のコンストラクター コードを100% コピーすることができました。

この最後の追加により、CSVFile Iteratorを使用する元のコードをそのまま維持することもできます。

$csv = new CSVFile('../data/test.csv');

foreach ($csv as $line) {
    var_dump($line);
}

したがって、より多くのコードを再利用できるようにするための簡単なリファクタリングです。無料でKeyedArrayIteratorを取得できます。

于 2012-04-16T20:34:55.677 に答える
4
$csv_data = array_map('str_getcsv', file('Book.csv'));// reads the csv file in php array
$csv_header = $csv_data[0];//creates a copy of csv header array
unset($csv_data[0]);//removes the header from $csv_data since no longer needed
foreach($csv_data as $row){
    $row = array_combine($csv_header, $row);// adds header to each row as key
    var_dump($row);//do something here with each row
}
于 2016-03-19T05:13:56.290 に答える
3
function processCsv($absolutePath)
{
    $csv = array_map('str_getcsv', file($absolutePath));
    $headers = $csv[0];
    unset($csv[0]);
    $rowsWithKeys = [];
    foreach ($csv as $row) {
        $newRow = [];
        foreach ($headers as $k => $key) {
            $newRow[$key] = $row[$k];
        }
        $rowsWithKeys[] = $newRow;
    }
    return $rowsWithKeys;
}
于 2014-10-15T10:29:38.007 に答える
1

この時点で、私はあなたがすでに問題を解決していると仮定していますが、おそらく最善/最もエレガントな解決策ではありませんが、これはうまくいきます:

$row = 1;
$array = array();
$marray = array();
$handle = fopen('file.csv', 'r');
if ($handle !== FALSE) {
    while (($data = fgetcsv($handle, 0, ',')) !== FALSE) {
        if ($row === 1) {
            $num = count($data);
            for ($i = 0; $i < $num; $i++) {
                array_push($array, $data[$i]);
            }
        }
        else {
            $c = 0;
            foreach ($array as $key) {
                $marray[$row - 1][$key] = $data[$c];
                $c++;
            }
        }
        $row++;
    }
    echo '<pre>';
    print_r($marray);
    echo '</pre>';
}
于 2016-03-09T10:42:09.317 に答える
0

このコードで試してください:

$query = "SELECT * FROM datashep_AMS.COMPLETE_APPLICATIONS";
$export= mysql_query($query);
$first = true;
$temp = $export[0];
//echo "<pre>"; print_r($first); exit;

header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename=file.csv');
header('Pragma: no-cache');
header("Expires: 0");

$outstream = fopen("php://output", "w");



foreach($export as $result)
{
    if($first){
        $titles = array();
        foreach($temp as $key=>$val){
            $titles[] = $key;
        }
        //print_r ($titles);exit;
        fputcsv($outstream, $titles);
    }
    $first = false;
    fputcsv($outstream, $result);
}

fclose($outstream);

ありがとう

于 2014-01-16T12:48:55.503 に答える