0

Well, I need to parse 2 textfiles. 1 named Item.txt and one named Message.txt They are configuration files for a game server, Item contains a line for each item in the game, and Message has Item names, descriptions, server messages etc. I know this is far less than ideal, but I can't change the way this works, or the format.

The idea is in Item.txt I have lines in this format

(item (name 597) (Index 397) (Image "item030") (desc 162) (class general etc) (code 4 9 0 0) (country 0 1 2) (plural 1) (buy 0) (sell 4) )

If I have the php variable $item which is equal to 397 (Index), I need to first get the 'name' (597).

Then I need to open Message.txt and find this line

( itemname 597 "Blue Box")

Then return "Blue Box" to PHP as a variable.

What I'm trying to do is return the item's name with the item's Index.

I know this is probably something really basic, but I've searched though dozens of file operation tutorials and still can't seem to find what I need.

Thanks

Zen
  • 7,197
  • 8
  • 35
  • 57
  • I don't get it. Please give **much more** information about the structure in the text file and the desired output. – Gordon Jan 20 '11 at 20:40
  • 1
    Have you considered using a database for this instead? Most support foreign keys, which are made for just this kind of situation. Failing that, CSV files would be far simpler to process than your format, as you have explode and fgetcsv at your disposal. – GordonM Jan 20 '11 at 20:45
  • 1
    The problem is that the text file storage system is being used by a game server, and I can't change that. Also manual data entry of 5k or so items in a table isn't appealing. – Zen Jan 20 '11 at 20:49
  • If the only option is manual data entry you won't have much luck coding it in php either. – Captain Giraffe Jan 20 '11 at 21:09
  • How about using an [s-expression parser](https://github.com/drslump/sexp-php) (PHP has several), read it into a database and if the modified date of the source files change, repopulate the database? – Erk Jan 17 '23 at 20:23

4 Answers4

2

Following method doesn't actually 'parse' the files, but it should work for your specific problem...

(Note: not tested)

Given:

$item = 397;

open Item.txt:

$lines = file('Item.txt');

search index $item and get $name:

$name = '';
foreach($lines as $line){ // iterate lines
    if(strpos($line, '(Index '.$item.')')!==false){
        // Index found
        if(preg_match('#\(name ([^\)]+)\)#i', $line, $match)){
            // name found
            $name = $match[1];
        }
        break;
    }
}
if(empty($name)) die('item not found');

open Message.txt:

$lines = file('Message.txt');

search $name and get $msg:

$msg = '';
foreach($lines as $line){ // iterate lines
    if(strpos($line, 'itemname '.$name.' "')!==false){
        // name found
        if(preg_match('#"([^"]+)"#', $line, $match)){
            // msg found
            $msg = $match[1];
        }
        break;
    }
}

$msg should now contain Blue Box:

echo $msg;
Floern
  • 33,559
  • 24
  • 104
  • 119
1

Not sure if your problem is with parsing the expressions, or reading files per se since you mention "file operation tutorials".

Those parenthetical expressions in your files are called s-expressions. You may want to google for an s-expression parser and adapt it to php.

Jong Bor Lee
  • 3,805
  • 1
  • 24
  • 27
1

You should look into the serialize function, which allows data to be stored to a textfile in a format that PHP can reinterpret easily when it needs to be reloaded.

Serializing this data as an array and saving it down to the textfiles would allow you to access it by array keys. Let's take your example. As an array, the data you described would look something like this:

$items[397]['name'] = 'bluebox';

Serializing the item array would put it in a format that could be saved and later accessed.

$data = serialize($items);
//then save data down to the text files using fopen or your favorite class

You could then load the file and unserialize it's contents to end up with the same array. The serialize and unserialize functions are directly intended for this application.

DeaconDesperado
  • 9,977
  • 9
  • 47
  • 77
  • After edits were made specifying that the data must be in s-expressions, I realize my solution is less practical. Still, this is a reliable and easy way to store PHP data in a recallable fashion. – DeaconDesperado Jan 20 '11 at 21:05
0

the first text file has several features that you can use to help parse it. It is up to you to decide if it is well formed and reliable enough to key on.

I noticed:

1) a record is delimited by a single line break
2) the record is further delimted by a set of parens () 
3) the record is typed using a word (e.g. item)
4) each field is delimited by parens 
5) each field is named and the name is the first 'word' 
6) anything after the first word is data, delimited by spaces
7) data with double quotes are string literals, everything else is a number

A method:

read to the end of line char and store that
strip the opening and closing parens
strip all closing )
split at ( and store in temp array (see: http://www.php.net/manual/en/function.explode.php)
element 0 is the type (e.g. item)
for elements 1-n, split at space and store in temp array.
element 0 in this new array will be the key name, the rest is data
once you have all the data compartmentalized, you can then store it in an associative array or database. The exact structure of the array is difficult for me to envision without actually getting into it.
horatio
  • 1,426
  • 8
  • 7