2015-02-10 33 views
0

我有2个.csv文件,其中第一列具有相似的值,包含的代码只做一行,它只做一次迭代,请帮助我修改代码...如何从一个csv文件解析多行使用php

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"); 

} 
+0

什么在CSV文件中? – GuyT 2015-02-10 12:06:06

+0

我不明白。你可以说得更详细点吗? – 2015-02-10 12:09:00

+0

请更具体地说明您正在尝试做什么。没有进一步的信息,你的代码很难阅读。另外,来自两个csv文件的一些测试数据都会很好。我是否正确地使用csv1和csv2的子集创建第三个csv文件? – Jojo 2015-02-10 12:20:59

回答

1

首先,让我们调试脚本。如果你遵循你的算法并仔细看看php的文件处理,那么为什么你只为第一行获得你想要的结果是显而易见的。

您正在脚本的开头打开这两个文件。 PHP在文件的开头为每个文件设置一个文件指针。让我们说在第一行以便于理解。

您的第一个while循环遍历您想要根据每个文件中相同的第一个字段加入内容的详细信息文件(hbarefined.csv)。然后,你开始一个while循环,读取hostrefined.csv的每一行。如果你找到了你想要的主键的行,你可以将来自hbarefined和hostrefined的两行内容加入并写入test.csv。在这里,我们有你的脚本的前两个故障。

  1. 即使您与主键不匹配,您也会为test.csv写一行新行。结果看起来很丑。

  2. 您正在为test.csv创建自己的csv格式。别!看看fputcsv()

什么你不知道的是,你的第二个while循环向前移动的文件指针hostrefined.csv一行对于每次迭代,但不会重置它达到结束的时候的文件。因为您通读了hbarefined.csv每行的整个hostrefined.csv,所以您在第一次while循环的第一次迭代后到达了结尾。第二次和所有即将到来的第一次while循环的迭代开始在hostrefined.csv结尾读取,因此永远不会找到匹配的行。在第一个while循环的每次迭代结束时,您需要使用。

$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"); 

另外,尽量与你的可变名称清晰。使用$ s作为索引变量在for循环中连续2次会令人困惑。什么是$ 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

享受

+0

完美的作品..谢谢@Jojo – 2015-02-12 07:00:05