【问题标题】:How do you unserialize multiple strings of data with a loop?如何使用循环反序列化多个数据字符串?
【发布时间】:2019-06-14 21:33:18
【问题描述】:

问题

我有一个从 mysql 数据库导出的大型 csv 文件。该文件的一列中包含序列化的字符串。我正在尝试找到一种方法:

  1. 反序列化列的每个字符串(位于自己的单元格中)
  2. 以某种方式输出它,使文本的格式与此类似:
    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"";}

问题

  1. 是否可以遍历序列化的数据,然后将其反序列化并以所需的格式显示(例如,以 HTML table 格式)?

注意:虽然这个序列化数据来自 MySQL 数据库,但如果可能的话,我宁愿不必再次挂接到数据库来检索这个序列化数据。

尝试的解决方案

到目前为止,我有:

  1. 查看了php文档http://php.net/manual/en/function.unserialize.php
  2. 查看 Stack Overflow 上的代码示例
  3. 用过http://unserialize.onlinephpfunctions.com/这样的工具来看看这个功能怎么用
  4. 尝试实现我自己的代码(见下文)

阅读主题/问题后,我知道我可能需要使用:

  1. 循环(遍历序列化数据)
  2. var_exportvar_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 个 &lt;tr&gt; 标签(但没有来自 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 代码添加到循环中)。

问题:

  1. 我在the PHP fgetscsv manual 的cmets 中读到,如果您是mac 用户(我是),您需要将auto_detect_line_endings 添加到您的代码中。我已经尝试过了,并没有发现任何区别。这可能是问题的一部分吗?
  2. fclose($fp); 在 @geoffrey 的代码和我上面粘贴的代码中的位置不同。尝试在我的代码/循环的不同行/区域中使用它,但没有运气。这是我在代码中使用 unserialized 时看不到任何内容的部分原因吗?
  3. 我可能遗漏了什么?

再次感谢您的任何见解。非常感谢!

更新 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


【解决方案1】:

由于您正在处理 CSV,我假设您希望读取文件并迭代您希望反序列化的数据位于第 5 列的每一行。我还假设所需的 HTML 输出格式,这个应该足以让您上路。

<table>
<?PHP
  $fp = fopen('file.csv', 'r');
  while(($row = fgetcsv($fp)) !== false)
  {
    echo "<tr>";
    $data = unserialize($row[5]);
    foreach($data as $name => $value)
    {
      echo "<td>" . htmlspecialchars($name ) . "</td>";
      echo "<td>" . htmlspecialchars($value) . "</td>";
    }
    echo "</tr>";
  }
  fclose($fp);
?>
</table>

您可能需要查看fgetcsv 上的文档,因为您可能需要根据您的 CSV 格式指定其他参数。

【讨论】:

  • 请不要将 cmets 用于代码,请根据您的尝试和结果更新您的问题。另请注意,由于您没有提供 CSV 样本,我们正在盲目工作。
  • 我已经更新了我上面的问题。感谢您的耐心和帮助。
  • 提供的示例文件不是CSV,您确定这是您要解析的正确文件吗?您显示的文件只是多行 PHP 序列化数据。如果您真正使用的是 CSV,请提供包含多列的实际 CSV,以便我们能够真正了解代码的情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-22
  • 1970-01-01
  • 2015-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多