[英]How to read a range of rows from CSV file to JSON array using PHP to handle large CSV file?
[英]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个故障。
即使您与主键不匹配,也要在test.csv中写一个新行。 结果看起来很丑。
您正在自己为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.