簡體   English   中英

如何使用php解析csv文件中的多行

[英]how to parse multiple rows from a csv file using php

我有2個.csv文件,它們的第一列具有相似的值,所包含的代碼僅對一行執行該工作,僅進行一次迭代,請幫助我修改代碼...

hostrefined.csv contents...
name1,23423,detail1
name2,12312,detail2
name3,21312,detail3

hbarefined.csv contents...
name1,det1,det2,2323
name1,det3,det4,23434
name1,det5,det6,34343
name2,det9,det7,232322
name3,det10,det28,232

the output file has to be like

name1,23423,detail1,det1,det2,2323
name1,23423,detail1,det3,det4,23434
name1,23423,detail1,det5,det6,34343
name2,12312,detail2,det9,det7,232322
name3,21312,detail3,det10,det28,232

代碼在這里

$handle = fopen("hostsrefined.csv", "r");
$handle1 = fopen("hbarefined.csv", "r");

$fp=fopen('test.csv','w');
while($data1 = fgetcsv($handle1, 1000, ","))
{
while($data = fgetcsv($handle, 1000, ","))
{
    if($data1[0]==$data[0])
    {
        for($s=0;$s<9;$s++)  // to write data from first .csv file
        {

            fwrite($fp,$data[$s]);
            fwrite($fp,",");
        }
        for($s=1;$s<6;$s++)     // to write data frm second .csv file
        {


                fwrite($fp,$data1[$s]);
                fwrite($fp,",");

        }

    }

    fwrite($fp,"\n");
}fwrite($fp,"\n");

}

首先,讓我們調試腳本。 如果您遵循算法並仔細研究php的文件處理,那么為什么只在第一行獲得所需結果的問題就很明顯。

您將在腳本的開頭打開兩個文件。 PHP在文件的開頭為每個文件設置一個文件指針。 為了便於理解,我們在第一行說。

您的第一個while循環通過您的詳細信息文件(hbarefined.csv),您要在其中基於每個文件中相等的第一個字段來聯接內容。 然后,啟動一個while循環,該循環讀取hostrefined.csv的每一行。 如果找到具有所需主鍵的行,則將hbarefined和hostrefined中的兩行內容合並,並將其寫入test.csv。 這里有您腳本的前2個故障。

  1. 即使您與主鍵不匹配,也要在test.csv中寫一個新行。 結果看起來很丑。

  2. 您正在自己為test.csv創建csv格式。 別! 看看fputcsv()

您所不知道的是,您的第二個while循環將每次迭代的hostrefined.csv的文件指針向前移動了一行,但是到達文件末尾時並沒有將其重置。 因為您遍歷了hbarefined.csv的每一行的整個hostrefined.csv,所以您在第一個while循環的第一次迭代之后到達了結尾。 第一個while循環的第二個以及所有即將到來的迭代將在hostrefined.csv的末尾開始讀取,因此將永遠找不到匹配的行。 您需要在第一個while循環的每次迭代結束時使用rewind()

$handle = fopen("hostsrefined.csv", "r");
$handle1 = fopen("hbarefined.csv", "r");

$fp=fopen('test.csv','w');
while($data1 = fgetcsv($handle1, 1000, ","))
{
while($data = fgetcsv($handle, 1000, ","))
{
    if($data1[0]==$data[0])
    {
        for($s=0;$s<9;$s++)  // to write data from first .csv file
        {

            fwrite($fp,$data[$s]);
            fwrite($fp,",");
        }
        for($s=1;$s<6;$s++)     // to write data frm second .csv file
        {


                fwrite($fp,$data1[$s]);
                fwrite($fp,",");

        }

    }

    fwrite($fp,"\n");
}
fwrite($fp,"\n");
rewind($handle);
}

那將修復您的腳本。

一些一般性注意事項:您的代碼很難閱讀,這使我難以調試和修復。 正確使用縮進,並對新命令使用換行,請考慮以下示例:

while($data = fgetcsv($handle, 1000, ","))
{
    // ...some code
}fwrite($fp,"\n");

另外,請嘗試使用您的變量名弄清楚。 在連續兩次for循環中使用$ s作為索引變量會造成很多混亂。 什么是$ fp? 你懂我...

我重寫了您的代碼以供參考:

<?php
/**
 * Goal of this script is to read a csv-file with a primary-key (input-primary.csv)
 * in field 0 and join contents from a second csv-file (input-detail.csv).
 * Each row in input-detail.csv has the primary key from input-primary.csv
 * in field 0 as well.
 * This script needs php version 5.4 o higher
 */

/**
 * First, we define some helper functions
 */

/**
 * Read csv-contents from $filename and return it indexed by primary-key.
 * Primary-key is in field 0
 * 
 * @param string $filename file to read
 * @return array
 */
function getCsvContentIndexedByPrimaryKey($filename)
{
    $handle = fopen($filename, 'r');
    $indexedContents = [];
    while (false !== $row = fgetcsv($handle)) {
        $primaryKey = $row[0];
        $indexedContents[$primaryKey] = $row;
    }

    return $indexedContents;
}

/**
 * Joins contents from $row and $indexedContents by index taken from 
 * field 0 of $row. Primarykey-field of $row will be unset. If no content
 * was found in $indexedContents an exception is thrown with the primary-key.
 * 
 * @param array $row row from input-detail.csv
 * @param array $indexContents result from getCsvContentIndexedByPrimaryKey
 * @return array joined content
 * @throws Exception if no content for $row[0] was found in $indexedContents
 */
function joinRowByPrimaryKey($row, $indexedContents)
{
    $primaryKey = $row[0];
    if (isset($indexedContents[$primaryKey])) {
        $contentToJoin = $indexedContents[$primaryKey]; unset($row[0
        ]); return array_merge($contentToJoin, $row);
    }
    throw new \Exception(sprintf(
        'Primary-key %s not found in indexed-contents', $row[0]));
}

/**
 * Now, here we go.
 */

// we create the indexed-content and initialize our output and error-handling
$indexedContents = getCsvContentIndexedByPrimaryKey('input-primary.csv');
$outputContent = [];
$errors = [];

// now we read the second csv-file
$handle = fopen('input-detail.csv', 'r');
while (false !== $row = fgetcsv($handle)) {
    try {
        $outputContent[] = joinRowByPrimaryKey($row, $indexedContents);
    } catch (\Exception $e) { // we catch the exception from joinRowByPrimaryKey here
        $errors[$row[0]] = $e->getMessage();
    }
}

// Finally, we create our result-file and write our output-content to it
// note the usage of fputcsv @see http://php.net/fputcsv
// there is no need to manually write commas, line-endings and the like
$handle = fopen('result.csv', 'w');
foreach ($outputContent as $row) {
    fputcsv($handle, $row);
}

// and print our errors
foreach ($errors as $error) {
    echo $error . PHP_EOL;
}

帶有示例csv文件的代碼也在github上: https : //github.com/jbrinksmeier/so-28431197

請享用

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM