如何解决将PHP mySQL与包含BOM的CSV数据结合使用
我有一个数据库,该数据库保存不同供应商提供的某些商品的库存水平。每个供应商都会向我发送每日CSV文件以及其当前库存水平。我正在尝试将库存水平更新到我的数据库中。
我遇到的问题是,当我从CSV中提取数据并通过查询发送数据时,它无法正常工作。
在发送查询之前,我已经回显了查询,并且输出很好。使用PHPMyAdmin,如果我只是粘贴回显的代码,它就可以正常工作。这使我相信这是一个编码问题。
在cPanel文件管理器中查看CSV文件,我发现文件开头有一个奇数字符。 (我相信这是生成BOM的方法)。如果删除此字符并保存CSV文件,则我的代码可以正常工作,并且数据库将按预期更新。
在cPanel文件管理器中编辑文件,编码将以ansi_x3.110-1983打开。虽然手动删除角色可以解决问题,但是这不是一个选项,因为我希望这是一个全自动的日常流程。
// Open File
$csvData = fopen($file,"r");
if($csvData !== FALSE)
{
while(!feof($csvData))
{
$csvRow[] = fgetcsv($csvData,100);
}
}
// Close file
fclose($csvData);
foreach($csvRow as $row)
{
$searchQuery = "SELECT * FROM supplier WHERE supplierItemCode = '".$row[0]."'";
$result = $conn->query($searchQuery);
echo "<br>".$searchQuery;
if($result->num_rows > 0)
{
// CODE NEVER REACHES HERE
}
如前所述,如果我简单地将$searchQuery
的回显粘贴到PHPMyAdmin中并运行查询,它将正常工作。
我尝试使用fseek($csvData,2)
来成功从数据的第一行中删除BOM字符,但这无效。
根据建议,我尝试使用
$csvData = fopen($file,"r");
$BOM = null;
if($csvData !== FALSE)
{
$BOM = fread($csvData,3);
if($BOM !== FALSE)
{
if($BOM != "\xef\xbb\xbf")
{
echo "<h5>BOM: ".$BOM; // This code is executed every time
fseek($csvData,0);
}
}
//fseek($csvData,2); // This was my earlier attempts without the above BOM filter
while(!feof($csvData))
{
$csvRow[] = fgetcsv($csvData,100);
}
}
作为进一步的说明,您会注意到在我的Update查询输出中,SET数量列中有一个空格。该空间在csv文件中不可见。
此查询的构建依据
$updateQuery = "UPDATE supplier SET ".$supplier." = '".$row[2]."' WHERE supplierItemCode = '".$row[0]."'";
有关导致此问题的确切原因以及如何解决此问题的任何建议。
谢谢。
解决方法
尝试对打开和读取CSV文件的代码进行以下修改。它会检查BOM表的存在并绕过它(如果存在):
$cvsRow = [];
// Open File
$csvData = fopen($file,"r");
if($csvData !== FALSE)
{
$BOM = fread($csvData,4); // read potential BOM sequences to see if one is present or not
if ($BOM !== FALSE)
{
if (strlen($BOM) >= 3 && substr_compare($BOM,"\xef\xbb\xbf",3) == 0)
{
fseek($csvData,3); // found UTF-8 encoded BOM
}
elseif (strlen($BOM) >= 2 && (substr_compare($BOM,"\xfe\xff",2) == 0 || substr_compare($BOM,"\xff\xfe",2) == 0))
{
fseek($csvData,2); // found UTF-16 encoded BOM
}
elseif ($BOM != "\00\00\xfe\xff" && $BOM != "\xff\xfe\00\00")
{
fseek($csvData,0); // did not find UTF-32 encoded BOM
}
while(!feof($csvData))
{
$csvRow[] = fgetcsv($csvData,100);
}
}
// Close file (only if it has been successfully opened)
fclose($csvData);
}
,
我终于有了解决方案。经过大量调查,尽管BOM字符可能在说什么,但我相信它是用UTF-16编码的。
我刚刚编写了一个简单的函数来转换要传递给SQL的每个CSV值。
function Convert($str)
{
return mb_convert_encoding($str,"UTF-8","UTF-16BE");
}
........
$updateQuery = "UPDATE supplier SET ".$supplier." = '".Convert($row[2])."' WHERE supplierItemCode = '".Convert($row[0])."'";
我不确定为什么BOM会导致此类问题,以及为何将其完全删除无法正常工作。感谢大家的帮助,这使我发现了编码问题。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。