【发布时间】:2021-10-06 14:35:30
【问题描述】:
我有很多第三方生成的 csv 文件,对此我没有发言权或控制权。
所以我每天都要将这些csv数据导入mysql。
有些表的列数与标题匹配正确。
其他人没有。
即使我做了一个准备好的语句,它仍然没有导入。
我尝试创建一个修复 csv 函数,如果它们的列数小于标题列数,则为每一行添加额外的列。
作为这个项目的一部分,我正在使用 composer 包联盟 csv。
但这是我的功能代码:
public function repaircsv(string $filepath) {
// make sure incoming file exists
if (!file_exists($filepath)) {
// return nothing
return;
}
// setup variables
$tempfile = pathinfo($filepath,PATHINFO_DIRNAME).'temp.csv';
$counter = 0;
$colcount = 0;
$myline = '';
// check if temp file exists if it does delete it
if (file_exists($tempfile)) {
// delete the temp file
unlink($tempfile);
}
// C:\Users\admin\vendor\league\csv
require('C:\Users\admin\vendor\league\csv\autoload.php');
// step one get header column count
$csv = Reader::createFromPath($filepath);
// set the header offset
$csv->setHeaderOffset(0);
//returns the CSV header record
$header = $csv->getHeader();
// get the header column count
$header_count = count($header);
// check if greater than zero and not null
if ($header_count < 1 || empty($header_count)) {
// return nothing
return $header_count;
}
// loop thru csv file
// now read file line by line skipping line 1
$file = fopen($filepath, 'r');
$temp = fopen($tempfile, 'w');
// loop thru each line
while (($line = fgetcsv($file)) !== FALSE) {
// if first row just straight append
if ($counter = 0) {
// append line to temp file
fputcsv($temp, $line);
}
// if all other rows compare column count to header column count
if ($counter > 0) {
// get column count for normal rows
$colcount = count($line);
// compare to header column count
$coldif = $header_count - $colcount;
// loop til difference is zero
while ($colcount != $header_count) {
// add to line extra comma
$line .= ',';
// get new column count
$colcount = count($line);
}
// append to temp file
fputcsv($temp, $line);
// show each line
$myline .= 'Line: ['.$line.']<br/><br/>';
}
// increment counter
$counter++;
}
// check file size of temp file
$fs = filesize($tempfile);
// if below 200 ignore and do not copy
if ($fs > 200) {
// copy temp to original filename
copy($tempfile,$filepath);
}
return $myline;
}
逻辑是将原始 csv 文件复制到一个新的临时 csv 文件,并在缺少列的数据行中添加额外的逗号。
感谢您的帮助。
编辑:所以各种csv包含私人数据,所以我不能分享它们。
但是,例如,假设我每天为不同的数据下载多个 csv。
每个 csv 都有一个标题行和数据。
如果每行中的列数与标题中的列数不是 100% 相同,则会出错。
如果有特殊字符,会报错。
有 1000 行数据。
上面的代码是我第一次尝试修复缺少列的行。
这是一个例子 名:姓:电子邮箱 史蒂夫,乔布斯 ,约翰逊,sj@johns.com
只是一个很小的例子。
我无法控制 csv 的创建方式,我可以控制下载过程和导入过程。
然后我使用 csv 数据来更新 mysql 表。
我已经尝试过加载数据 infile,但也出现了错误。
所以我需要在下载 csv 文件后对其进行修复。
有什么想法吗?
【问题讨论】:
-
不太清楚问题是什么:您是否有一个示例文件,其中您的代码没有给出您需要的结果?
-
CSV 是否有标题行?如果是这样,那会让事情变得更容易。如果没有,你会很头疼
-
如果数据中的列数与标题的列数不匹配,则生成的 csv 文件有问题。文件中的各个行的列数是否不同,或者文件中所有数据行的列数是否一致?这可能是一个线索。
-
它们确实变化很大,而且任何时候一行与列数不匹配,它都会停止整个导入过程。
-
"它会停止整个导入过程。" 否则您会发生什么?你怎么可能以编程方式知道哪些列“丢失”了?如果您要猜测或只是在文件末尾添加空白列,那么您将面临将数据本身从列标题中解构的极端风险。出现这些错误是有原因的,除了修复上游流程之外,没有可靠的方法来解决这个问题。