[英]Parsing flat-file database information into a multidimensional array
我想创建一个类,用于将平面文件数据库信息解析为一个大型的类似多维数组。 我想到了以某种python-esque格式格式化数据库的想法,如下所示:
"tree #1":
"key" "value"
"sub-tree #1":
"key" "value"
"key #2" "value"
"key #3" "value"
我试图使其解析并构建和数组,同时解析它以将键/值放入其中,并且我希望它具有很高的动态性和可扩展性。 我尝试了许多不同的技术,但每次尝试都让我感到困惑。 这是我最近的:
function parse($file=null) {
$file = $file ? $file : $this->dbfile;
### character variables
# get values of
$src = file_get_contents($file);
# current character number
$p = 0;
### array variables
# temp shit
$a = array();
# set $ln keys
$ln = array("q"=>0,"k"=>null,"v"=>null,"s"=>null,"p"=>null);
# indent level
$ilvl = 0;
### go time
while (strlen($src) > $p) {
$chr = $src[$p];
# quote
if ($chr == "\"") {
if ($ln["q"] == 1) { // quote open?
$ln["q"] = 0; // close it
if (!$ln["k"]) { // key yet?
$ln["k"] = $ln["s"]; // set key
$ln["s"] = null;
$a[$ln["k"]] = $ln["v"]; // write to current array
} else { // value time
$ln["v"] = $ln["s"]; // set value
$ln["s"] = null;
}
} else {
$ln["q"] = 1; // open quote
}
}
elseif ($chr == "\n" && $ln["q"] == 0) {
$ln = array("q"=>0,"k"=>null,"v"=>null,"s"=>null,"p"=>null);
$llvl = $ilvl;
}
# beginning of subset
elseif ($chr == ":" && $ln["q"] == 0) {
$ilvl++;
if (!array_key_exists($ilvl,$a)) { $a[$ilvl] = array(); }
$a[$ilvl][$ln["k"]] = array("@mbdb-parent"=> $ilvl-1 .":".$ln["k"]);
$ln = array("q"=>0,"k"=>null,"v"=>null,"s"=>null,"p"=>null);
$this->debug("INDENT++",$ilvl);
}
# end of subset
elseif ($chr == "}") {
$ilvl--;
$this->debug("INDENT--",$ilvl);
}
# other characters
else {
if ($ln["q"] == 1) {
$ln["s"] .= $chr;
} else {
# error
}
}
$p++;
}
var_dump($a);
}
老实说,我不知道从这里去哪里。 让我最困扰的是我在这里设置多维值的方法,例如$this->c["main"]["sub"]["etc"]
。 还能做到吗? 当数据嵌套在db文件中时,如何实际嵌套数组?
这一切都取决于您希望“平面文件”具有怎样的可读性。
想要人类可读?
半人类可读?
真的不可读吗?
编写自己的格式会很痛苦。 除非您纯粹是出于学术经验,否则我不会打扰。
看起来JSON可能是您的理想选择。
$configData = array(
'tree #1' => array(
'key' => 'value'
, 'sub-tree #1' => array(
'key' => 'value'
, 'key #2' => 'value'
, 'key #3' => 'value'
)
)
);
// Save config data
file_put_contents( 'path/to/config.json', json_format( json_encode( $configData ) ) );
// Load it back out
$configData = json_decode( file_get_contents( 'path/to/config.json' ), true );
// Change something
$configData['tree #1']['sub-tree #1']['key #2'] = 'foo';
// Re-Save (same as above)
file_put_contents( 'path/to/config.json', json_format( json_encode( $configData ) ) );
您可以在此处获得json_format()
函数,该函数的格式很漂亮,便于人们阅读。 如果您不关心人类可读性,则可以跳过它。
好吧,您可以使用序列化和反序列化,但这不会很有趣,对吗? 您应该使用专门为此目的设计的格式,但是为了便于练习,我将尝试看看能提供些什么。
平面文件中似乎有两种数据类型,即键值对和数组。 键值对用两组引号和带有一对引号和后跟冒号的数组表示。 浏览文件时,必须分析每一行并确定它代表什么。 使用正则表达式很容易。 困难的部分是跟踪我们要达到的水平并采取相应的措施。 这是一个解析您提供的树的函数:
function parse_flatfile($filename) {
$file = file($filename);
$result = array();
$open = false;
foreach($file as $row) {
$level = strlen($row) - strlen(ltrim($row));
$row = rtrim($row);
// Regular expression to catch key-value pairs
$isKeyValue = preg_match('/"(.*?)" "(.*?)"$/', $row, $match);
if($isKeyValue == 1) {
if($open && $open['level'] < $level) {
$open['item'][$match[1]] = $match[2];
} else {
$open = array('level' => $level - 1, 'item' => &$open['parent']);
if($open) {
$open['item'][$match[1]] = $match[2];
} else {
$result[$match[1]] = $match[2];
}
}
// Regular expression to catch arrays
} elseif(($isArray = preg_match('/"(.*?)":$/', $row, $match)) > 0) {
if($open && $open['level'] < $level) {
$open['item'][$match[1]] = array();
$open = array('level' => $level, 'item' => &$open['item'][$match[1]], 'parent' => &$open['item']);
} else {
$result[$match[1]] = array();
$open = array('level' => $level, 'item' => &$result[$match[1]], 'parent' => false);
}
}
}
return $result;
}
我不会更详细地介绍它是如何工作的,但是总之,随着我们深入到数组中,上一层存储在引用$open
,依此类推。 这是使用您的符号表示的更复杂的树:
"tree_1":
"key" "value"
"sub_tree_1":
"key" "value"
"key_2" "value"
"key_3" "value"
"key_4" "value"
"key_5" "value"
"tree_2":
"key_6" "value"
"sub_tree_2":
"sub_tree_3":
"sub_tree_4":
"key_6" "value"
"key_7" "value"
"key_8" "value"
"key_9" "value"
"key_10" "value"
要解析该文件,您可以使用:
$result = parse_flatfile('flat.txt');
print_r($result);
那会输出:
Array
(
[tree_1] => Array
(
[key] => value
[sub_tree_1] => Array
(
[key] => value
[key_2] => value
[key_3] => value
)
[key_4] => value
[key_5] => value
)
[tree_2] => Array
(
[key_6] => value
[sub_tree_2] => Array
(
[sub_tree_3] => Array
(
[sub_tree_4] => Array
(
[key_6] => value
[key_7] => value
[key_8] => value
[key_9] => value
[key_10] => value
)
)
)
)
)
我猜我的测试文件涵盖了所有基础,并且应该可以正常工作。 但是我不会提供任何保证。
使用此符号将多维数组转换为平面文件将留给读者练习:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.