微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将PHP mySQL与包含BOM的CSV数据结合使用

如何解决将PHP mySQL与包含BOM的CSV数据结合使用

我有一个数据库,该数据库保存不同供应商提供的某些商品的库存水平。每个供应商都会向我发送每日CSV文件以及其当前库存水平。我正在尝试将库存水平更新到我的数据库中。

我遇到的问题是,当我从CSV中提取数据并通过查询发送数据时,它无法正常工作。

在发送查询之前,我已经回显了查询,并且输出很好。使用PHPMyAdmin,如果我只是粘贴回显的代码,它就可以正常工作。这使我相信这是一个编码问题。

在cPanel文件管理器中查看CSV文件,我发现文件开头有一个奇数字符。 (我相信这是生成BOM的方法)。如果删除此字符并保存CSV文件,则我的代码可以正常工作,并且数据库将按预期更新。

enter image description here

在cPanel文件管理器中编辑文件,编码将以ansi_x3.110-1983打开。虽然手动删除角色可以解决问题,但是这不是一个选项,因为我希望这是一个自动的日常流程。

打开文件并从CSV提取数据的代码

// 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);
   }
}

使用BOM表筛选器方法将产生此输出

Sample output

作为进一步的说明,您会注意到在我的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 举报,一经查实,本站将立刻删除。