PHP解析自定义平​​面文本数据库

时间:2015-11-20 16:38:42

标签: php arrays

我有一个文本文件,用于存储有关不同项目的信息。

此文件是结构化的。文件中的每个项目都用花括号{}分隔,并以逗号开头。每个项目都有一个属性列表,属性可以存在或不存在。如果他们不在那里,服务器会认为他们是"默认"。

每个条目都用花括号括起来,以逗号结尾:{}, 该文件还包括标准C评论,//以及/ * * / 项目的每个属性都是从33个属性池中标准化的,其中只有3个属性是必需的。可以包含或省略属性。假定未包含的属性是后端程序的默认属性。 有一些属性可以是多行甚至多属性(如果愿意,可以形成一个数组)。

所以,文件粗略如下:

itemdb: (
 /*
 {    
  Multi line comment
  here to explain the file
  },
  */
  // Here starts the items
  {
    Id: 500
    DatabaseName: "Item_1"
    Name: "Item 1"
    Type: 1
    Buy: 40
    Weight: 10
  },
  {
    Id: 501
    DatabaseName: "Item_2"
    Name: "Item 2"
    Type: 1
    Sell: 600
    Weight: 200
    Script: <" do stuff; ">
  },
  // Here is some more items
  {
    Id: 637
    DatabaseName: "Item_137"
    Name: "Item 137"
    Type: 5
    Buy: 9000
    Weight: 300
    Trade: {
      nodrop: true
      notrade: true
    }
    Script: <" 
              do this stuff;
                 then this stuff;
              ">
 },
 // Note: Edited this in 2015-11-23, see below.
)

我需要一种方法将所有元素分解为数组以显示给用户。数组看起来像这样(来自上面的例子):

$itemDB = Array
(
    [500] => Array
    (
      [DatabaseName] => Item_1
      [Name] => Item 1
      [Type] => 1
      [Buy] => 40
      [Weight] => 10
    )
    [501] => Array
    (
      [DatabaseName] => Item_2
      [Name] => Item 2
      [Type] => 1
      [Sell] => 600
      [Weight] => 200
      [Script] => do stuff
    )
    [637] => Array
    (
      [DatabaseName] => Item_137
      [Name] => Item 137
      [Type] => 5
      [Buy] => 9000
      [Weight] => 300
      [Trade] => array
      (
         [nodrop] => true
         [notrade] => true
      )
      [Script] => do this stuff;\nthen this stuff
    )
);

(所以基本上将文件分成一个多维数组,文件的&#39; Id&#39;属性是每个数组的关键,文件的每个属性都是它自己的键/值)

我设法提出以下代码将数组分解为每个条目:

$ready = str_replace(array("{","}"),"|", $itemDB);
$itemDB_explode = explode("|", $ready);

然而,这段代码只让我到了一半。我基本上得到了这样一个数组:

[7]=> string(124) " Id: 501 DatabaseName: "Item_2" Name: "Item 2" Type: 1 Sell: 600 Weight: 200 Script: <" do stuff "> "

但是对于我的生活,我无法弄清楚如何让它比这更远,包括如何使数组的键成为Id,每个属性都有自己的键/值。

重点是向用户显示条目,允许他们进行编辑,然后将文件保存回来。希望我也能得到帮助以保存它。

对于毫无疑问会问的人:是的,我知道这样的东西更适合SQL数据库。问题是这个文件和后端读取和解释它不是我写的,我无法改变它。我只是编写基于Web的前端来轻松更改该文件。

提前感谢您提供的帮助。

修改2015-11-23 : 我从原来的问题中留下了一些属性。考虑对实际文件进行此编辑,添加缺少的属性:

 {
   Id: 845
   DatabaseName: "Item_345"
   Name: "Item 345"
   Type: 3
   Buy: 30000
   Nouse: {
     override: 30
     sitting: true
   }
   Stack: [99, 4]
   OnEquipScript: <" do this stuff; ">
   OnUnequipScript: <" 
                 do some more stuff;
                 this is some more stuff;
                      ">
 },

考虑结果数组对于文件中的附加块的外观:

    [845] => Array
    (
      [DatabaseName] => Item_345
      [Name] => Item 345
      [Type] => 3
      [Buy] => 30000
      [Nouse] => array
      (
         [override] => 30
         [sitting] => true
      )
      [Stack] =>
      (
         [0] => 99
         [1] => 4
      )
      [OnEquipScript] => do this stuff;
      [OnUnequipScript] => do some more stuff;\nthis is some more stuff;
   )

1 个答案:

答案 0 :(得分:3)

以为我可以在15分钟内把它关掉,而我却坐在那里,但是多线脚本让我最后都抓住了。所以花了35分钟,但我可以向你保证,你不在那里;)

<?php

$items = array();
$in_comment = false;
$in_trade = false;
$in_script = false;

$itemDB = file("foo.txt");

foreach ($itemDB as $row) {
    $row = trim($row);
    if (strpos($row, "//") === 0) continue;
    if (strpos($row, "/*") === 0) {
        $in_comment = true;
        continue;
    }
    if (strpos($row, "*/") === 0) {
        $in_comment = false;
        continue;
    }
    if ($in_comment) continue;
    if ($row === "itemdb: (") continue;
    if ($row === ")") continue;
    if (strpos($row, "{") === 0) {
        $item = array();
    }
    elseif (!$in_trade && strpos($row, "}") === 0) {
        $items[$item["Id"]] = $item;
    } else {
        $row = explode(":", $row);
        $key = trim($row[0]);
        $val = isset($row[1]) ? trim($row[1]) : "";
        if ($key === "Trade" && strpos($val, "{") === 0) {
            $in_trade = true;
            $item["Trade"] = array();
            continue;
        } elseif ($in_trade && $key === "}") {
            $in_trade = false;
            continue;
        } elseif ($key === "Script") {
            $in_script = true;
            $item["Script"] = "";
        }

        if ($in_trade) {
            $item["Trade"][$key] = $val;
        } elseif ($in_script) {
            $item["Script"] .= (empty($val) ? $key : $val) . "\n";
            if (strpos($key, "\">") !== false || strpos($val, "\">") !== false) {
                $item["Script"] = str_replace(array("<\"", "\">"), "", $item["Script"]);
                $item["Script"] = trim($item["Script"]);
                $in_script = false;
            }
        } else {
            $item[$key] = $val;
        }
    }
}

print_r($items);