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

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

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

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

在 cPanel 文件管理器中查看 CSV 文件时,我发现文件开头有一个奇怪的字符。(我相信这被称为 BOM)。如果我删除此字符并保存 CSV 文件,那么我的代码将完美运行并且数据库将按预期更新。

https://img1.sycdn.imooc.com/65351d920001afcd02900085.jpg

在 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

  }

如前所述,如果我只是将 echo 粘贴$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 过滤器方法会产生此输出。

https://img1.sycdn.imooc.com/65351da10001ec5605450098.jpg

进一步说明,您会注意到在我的更新查询输出中,SET 数量列中有一个空格。此空格在 csv 文件中不可见。

该查询是用构建的

$updateQuery = "UPDATE supplier SET ".$supplier." = '".$row[2]."' WHERE supplierItemCode = '".$row[0]."'";

关于到底是什么导致了这个问题以及如何解决这个问题的任何建议。

提前致谢。


米琪卡哇伊
浏览 71回答 2
2回答

慕妹3146593

我终于找到了可行的解决方案。经过大量调查后,我相信它是用 UTF-16 编码的,尽管 BOM 字符可能已经说明了这一点。我刚刚编写了一个简单的函数来转换我传递给 SQL 的每个 CSV 值。function Convert($str)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return mb_convert_encoding($str, "UTF-8", "UTF-16BE");&nbsp; &nbsp; }........$updateQuery = "UPDATE supplier SET ".$supplier." = '".Convert($row[2])."' WHERE supplierItemCode = '".Convert($row[0])."'";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;我不确定为什么 BOM 会导致此类问题,以及为什么完全删除它不起作用。感谢大家的帮助让我发现了编码问题。

暮色呼如

尝试对打开和读取 CSV 文件的代码进行以下修改。它检查 BOM 是否存在,如果存在则绕过它:$cvsRow = [];// Open File$csvData = fopen($file, "r");if($csvData !== FALSE){&nbsp; $BOM = fread($csvData, 4); // read potential BOM sequences to see if one is present or not&nbsp; if ($BOM !== FALSE)&nbsp; {&nbsp; &nbsp; if (strlen($BOM) >= 3 && substr_compare($BOM, "\xef\xbb\xbf", 0, 3) == 0)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; fseek($csvData, 3); // found UTF-8 encoded BOM&nbsp; &nbsp; }&nbsp; &nbsp; elseif (strlen($BOM) >= 2 && (substr_compare($BOM, "\xfe\xff", 0, 2) == 0 || substr_compare($BOM, "\xff\xfe", 0, 2) == 0))&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; fseek($csvData, 2); // found UTF-16 encoded BOM&nbsp; &nbsp; }&nbsp; &nbsp; elseif ($BOM != "\00\00\xfe\xff" && $BOM != "\xff\xfe\00\00")&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; fseek($csvData, 0); // did not find UTF-32 encoded BOM&nbsp; &nbsp; }&nbsp; &nbsp; while(!feof($csvData))&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; $csvRow[] = fgetcsv($csvData, 100);&nbsp; &nbsp; }&nbsp; }&nbsp; // Close file (only if it has been successfully opened)&nbsp; fclose($csvData);}
打开App,查看更多内容
随时随地看视频慕课网APP