如何通过循环反序列化多个数据字符串?

时间:2019-01-21 13:17:57

标签: php serialization

问题

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

  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. 查看有关堆栈溢出的代码示例
  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

尝试的解决方案

我创建了一个临时的CSV文件,该文件只有一列和10行。请参阅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代码添加到循环中)。

问题:

  1. 我在the PHP fgetscsv manual的注释中读到,如果您是Mac用户(我是),则需要在代码中添加auto_detect_line_endings。我已经尝试过了,没有发现任何区别。这可能是问题的一部分吗?
  2. @geoffrey的代码中和我上面粘贴的代码中fclose($fp);的位置是不同的。尝试在我的代码/循环的不同行/区域中使用它而没有运气。这是我在代码中使用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);

 ?>

希望这可以帮助其他遇到类似问题的人!

1 个答案:

答案 0 :(得分:0)

由于您正在处理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格式指定其他参数。