将 PHP mySQL 与包含 BOM 的 CSV 数据一起使用
Using PHP mySQL with CSV data containing BOM
我有一个数据库,用于保存由不同供应商提供的某些商品的库存水平。每个供应商都会每天向我发送一份 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 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 过滤器方法生成此输出。
作为进一步说明,您会注意到在我的更新查询输出中,SET 数量列中有一个空白 space。此 space 在 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", 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 != "[=10=][=10=]\xfe\xff" && $BOM != "\xff\xfe[=10=][=10=]")
{
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);
}
我终于找到了可行的解决方案。经过大量调查后,我相信它是用 UTF-16 编码的,尽管 BOM 字符可能一直在说什么。
我刚刚编写了一个简单的函数来将我传递的每个 CSV 值转换为 SQL。
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 会导致此类问题以及为什么完全删除它不起作用。感谢大家的帮助,让我发现了编码问题。
我有一个数据库,用于保存由不同供应商提供的某些商品的库存水平。每个供应商都会每天向我发送一份 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 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 过滤器方法生成此输出。
作为进一步说明,您会注意到在我的更新查询输出中,SET 数量列中有一个空白 space。此 space 在 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", 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 != "[=10=][=10=]\xfe\xff" && $BOM != "\xff\xfe[=10=][=10=]")
{
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);
}
我终于找到了可行的解决方案。经过大量调查后,我相信它是用 UTF-16 编码的,尽管 BOM 字符可能一直在说什么。
我刚刚编写了一个简单的函数来将我传递的每个 CSV 值转换为 SQL。
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 会导致此类问题以及为什么完全删除它不起作用。感谢大家的帮助,让我发现了编码问题。