为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

PHP
米琪卡哇伊 2023-10-22 21:02:17
我有一个数据库,其中保存了不同供应商提供的某些商品的库存水平。每个供应商每天都会向我发送一份包含当前库存水平的 CSV 文件。我正在尝试将库存水平更新到我的数据库中。我遇到的问题是,当我从 CSV 中提取数据并通过查询发送数据时,它无法正常工作。我在发送查询之前已经回显了查询,并且输出很好。使用 phpMyAdmin,如果我只是粘贴回显的代码,它就可以正常工作。这让我相信这是一个编码问题。在 cPanel 文件管理器中查看 CSV 文件时,我发现文件开头有一个奇怪的字符。(我相信这被称为 BOM)。如果我删除此字符并保存 CSV 文件,那么我的代码将完美运行并且数据库将按预期更新。在 cPanel 文件管理器中编辑文件,编码打开为 ansi_x3.110-1983。虽然手动删除角色可以解决问题,但这不是一个选项,因为我希望这是一个完全自动化的日常过程。我的代码用于打开文件并从 CSV 中提取数据:// Open File        $csvData = fopen($file, "r");       if($csvData !== FALSE){  while(!feof($csvData))  {      $csvRow[] = fgetcsv($csvData, 100);  }}// Close filefclose($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 过滤器方法会产生此输出。进一步说明,您会注意到在我的更新查询输出中,SET 数量列中有一个空格。此空格在 csv 文件中不可见。该查询是用构建的$updateQuery = "UPDATE supplier SET ".$supplier." = '".$row[2]."' WHERE supplierItemCode = '".$row[0]."'";关于到底是什么导致了这个问题以及如何解决这个问题的任何建议。提前致谢。
查看完整描述

2 回答

?
慕妹3146593

TA贡献1820条经验 获得超9个赞

我终于找到了可行的解决方案。经过大量调查后,我相信它是用 UTF-16 编码的,尽管 BOM 字符可能已经说明了这一点。


我刚刚编写了一个简单的函数来转换我传递给 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 会导致此类问题,以及为什么完全删除它不起作用。感谢大家的帮助让我发现了编码问题。


查看完整回答
反对 回复 2023-10-22
?
暮色呼如

TA贡献1853条经验 获得超9个赞

尝试对打开和读取 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", 0, 3) == 0)

    {

      fseek($csvData, 3); // found UTF-8 encoded BOM

    }

    elseif (strlen($BOM) >= 2 && (substr_compare($BOM, "\xfe\xff", 0, 2) == 0 || substr_compare($BOM, "\xff\xfe", 0, 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);

}


查看完整回答
反对 回复 2023-10-22
  • 2 回答
  • 0 关注
  • 68 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信