【发布时间】:2019-06-14 21:33:18
【问题描述】:
问题
我有一个从 mysql 数据库导出的大型 csv 文件。该文件的一列中包含序列化的字符串。我正在尝试找到一种方法:
- 反序列化列的每个字符串(位于自己的单元格中)
- 以某种方式输出它,使文本的格式与此类似:
array (
'weight' => '108 lbs', 'ah' => '24"', 'sw' => '50"', 'sdw' => '23"', 'shw' => '18"', 'sd' => '27"', 'sh' => '12"',
)
这是未序列化行的示例(其中大约有 1000 行):
a:7:{s:6:"weight";s:6:"30 lbs";s:2:"ah";s:3:"26"";s:2:"sw";s:3:"20"";s:3:"sdw";s:0:"";s:3:"shw";s:3:"19"";s:2:"sd";s:3:"19"";s:2:"sh";s:3:"17"";}
a:7:{s:6:"weight";s:7:"107 lbs";s:2:"ah";s:3:"26"";s:2:"sw";s:3:"72"";s:3:"sdw";s:3:"23"";s:3:"shw";s:3:"18"";s:2:"sd";s:3:"27"";s:2:"sh";s:3:"12"";}
a:7:{s:6:"weight";s:6:"37 lbs";s:2:"ah";s:0:"";s:2:"sw";s:0:"";s:3:"sdw";s:0:"";s:3:"shw";s:0:"";s:2:"sd";s:0:"";s:2:"sh";s:0:"";}
a:7:{s:6:"weight";s:6:"66 lbs";s:2:"ah";s:3:"26"";s:2:"sw";s:3:"50"";s:3:"sdw";s:3:"23"";s:3:"shw";s:3:"18"";s:2:"sd";s:3:"27"";s:2:"sh";s:3:"12"";}
a:7:{s:6:"weight";s:6:"30 lbs";s:2:"ah";s:0:"";s:2:"sw";s:3:"26"";s:3:"sdw";s:0:"";s:3:"shw";s:3:"18"";s:2:"sd";s:3:"39"";s:2:"sh";s:3:"12"";}
问题
- 是否可以遍历序列化的数据,然后将其反序列化并以所需的格式显示(例如,以 HTML
table格式)?
注意:虽然这个序列化数据来自 MySQL 数据库,但如果可能的话,我宁愿不必再次挂接到数据库来检索这个序列化数据。
尝试的解决方案
到目前为止,我有:
- 查看了php文档http://php.net/manual/en/function.unserialize.php
- 查看 Stack Overflow 上的代码示例
- 用过http://unserialize.onlinephpfunctions.com/这样的工具来看看这个功能怎么用
- 尝试实现我自己的代码(见下文)
阅读主题/问题后,我知道我可能需要使用:
- 循环(遍历序列化数据)
-
var_export或var_dump以所需格式显示内容
代码示例
这是我用来获得上述结果的代码:
<?php
$var1='a:7{s:6:"weight";s:7:"105lbs";s:2:"ah";s:3:"23"";s:2:"sw";s:3:"26"";s:3:"sdw";s:0:"";s:3:"shw";s:3:"17"";s:2:"sd";s:3:"80"";s:2:"sh";s:3:"12"";}';
$var2='a:7:{s:6:"weight";s:7:"108 lbs";s:2:"ah";s:3:"24"";s:2:"sw";s:3:"50"";s:3:"sdw";s:3:"23"";s:3:"shw";s:3:"18"";s:2:"sd";s:3:"27"";s:2:"sh";s:3:"12"";}';
$combined = unserialize($var2);
$combined2 = unserialize($var1);
print_r($combined);
print_r($combined2);
?>
虽然我没有得到想要的输出,但我可以让一些未序列化的数据出现在屏幕上:
Array ( [weight] => 108 lbs [ah] => 24" [sw] => 50" [sdw] => 23" [shw] => 18" [sd] => 27" [sh] => 12" ) Array ( [weight] => 105 lbs [ah] => 23" [sw] => 26" [sdw] => [shw] => 17" [sd] => 80" [sh] => 12" )
这是一个进步,但它是有问题的,因为它不是一个循环(手动输入)并且缺少 HTML 标记以便以后更容易格式化。
对此的任何见解将不胜感激。提前致谢!
更新 1
尝试的解决方案
我创建了一个只有一列和 10 行的临时 CSV 文件。请参阅 CSV 文件 here。
我尝试使用 @geoffry 共享的代码,但它似乎没有从我的 csv 文件中提取任何信息。我遇到了一个无限循环(控制台中显示了 1000 个 <tr> 标签(但没有来自 csv 文件的内容)。
在fgetscsv 指向正确的方向后,我找到了下面的代码。使用此代码,我能够以序列化形式将列放到页面上,因此我确定文件已正确打开。但是这个循环省略了反序列化步骤,这在这里更重要。
<?php
$filename = "myfilename.csv";
$id = fopen($filename, "r");
while ($data = fgetcsv($id, filesize($filename)))
$table[] = $data;
fclose($id);
echo "<table>\n";
foreach($table as $row)
{
echo "<tr>";
foreach($row as $data)
echo "<td>$data</td>";
echo "</tr>\n";
}
echo "</table>\n";
?>
我尝试将此代码的各个方面与下面的 @geoffrey 的代码组合在一起,但没有成功(例如,将 unserialize 代码添加到循环中)。
问题:
- 我在the PHP fgetscsv manual 的cmets 中读到,如果您是mac 用户(我是),您需要将
auto_detect_line_endings添加到您的代码中。我已经尝试过了,并没有发现任何区别。这可能是问题的一部分吗? -
fclose($fp);在 @geoffrey 的代码和我上面粘贴的代码中的位置不同。尝试在我的代码/循环的不同行/区域中使用它,但没有运气。这是我在代码中使用unserialized时看不到任何内容的部分原因吗? - 我可能遗漏了什么?
再次感谢您的任何见解。非常感谢!
更新 2
我能够使用名为maybe_unserialize 的辅助函数对序列化数据进行反序列化。虽然我无法遍历所有代码,但使用 PHP 获取非序列化数组是朝着正确方向迈出的一步。
代码示例
<?php
$original = array(
'a:7:{s:6:"weight";s:7:"149 lbs";s:2:"ah";s:3:"24"";s:2:"sw";s:3:"75"";s:3:"sdw";s:3:"23"";s:3:"shw";s:3:"18"";s:2:"sd";s:3:"27"";s:2:"sh";s:3:"12"";}'
);
$string = implode(", ", $original);
$done = maybe_unserialize($string);
var_export($done);
?>
希望这可以帮助其他有类似问题的人!
【问题讨论】:
-
所以你逐行读取文件并反序列化每一行。
-
你想要的输出是什么?
-
你所说的 是什么意思,并且缺少 HTML 标记以便以后更轻松地格式化?据我所知,序列化数据中没有 HTML?
-
代码示例搞砸了?我收到了一些通知:PHP 通知:unserialize(): Error at offset 0 of 144 bytes and Error at offset 30 of 145 bytes in...
-
“是否可以循环遍历序列化数据,然后反序列化它” - 不,你需要反过来 - 首先反序列化,然后循环结果结构中的任何内容都可以循环。 “这是未序列化行的示例” - 应该是 一个 行,还是这 五 行?
标签: php serialization