0

フラットファイル データベース情報を 1 つの大きな類似多次元配列に解析するためのクラスを作成したいと考えています。次のように、データベースを一種の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ファイルにネストされているため、実際に配列をネストするにはどうすればよいですか?

4

2 に答える 2

1

これはすべて、「フラットファイル」を人間が読める形式にするかどうかによって異なります。

人間が読める形式にしたいですか?

  • XML
  • Yaml

半人間可読?

  • JSON

本当に人間が読める形式ではありませんか?

  • シリアル化されたPHP(これもPHPのみ)
  • MySQLダンプ

独自のフォーマットを書くのは苦痛になります。あなたが純粋に学術的な経験のためにこれをしたいのでなければ、私は気にしないでくださいと言います。

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()で関数を取得できます。これは、人間が読みやすいようにきれいにフォーマットされています。人間の可読性を気にしない場合は、スキップできます。

于 2009-12-11T23:42:55.640 に答える
0

ええと、シリアライズアンシリアライズを使うことはできますが、それは面白くないでしょう?この目的のために特別に設計されたフォーマットを使用する必要がありますが、演習のために、私が思いつくことができるものを試してみます。

フラットファイルには、キーと値のペアと配列の2種類のデータ型があるようです。キーと値のペアは、2組の引用符と、1組の引用符とそれに続くコロンを持つ配列で示されます。ファイルを調べながら、各行を解析して、それが何を表しているかを判断する必要があります。正規表現を使えば簡単です。難しいのは、私たちが進んでいるレベルを追跡し、それに応じて行動することです。指定したツリーを解析する関数は次のとおりです。

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
                )    
            )    
        )    
    )    
)

私のテストファイルはすべてのベースをカバーしていると思います、そしてそれは壊れることなく動作するはずです。しかし、私は何の保証もしません。

この表記を使用して多次元配列をフラットファイルに変換することは、読者の練習問題として残されます:)

于 2009-12-11T23:35:38.077 に答える