У меня есть 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, даже если вы не соответствуете первичному ключу. Выглядит некрасиво в результате.
Вы сами создаете свой csv-формат для test.csv. Не надо! Посмотри на fputcsv ()
Чего вы не знаете, так это того, что ваш второй цикл while перемещает указатель файла для hostrefined.csv на одну строку вперед для каждой итерации, но не сбрасывает его при достижении конца файла. Поскольку вы прочитали весь hostrefined.csv для каждой строки hbarefined.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
наслаждаться
Других решений пока нет …