Hi, pals

Very simple question: I'm  parsing a txt file into an object, each line's content should go to a property inside my class. I'm using file.read_until(string) to catch and deliver content. I want to read until a line break, \r\n, but when I try using file.read_until("\r\n", true) it doesn't find any matches and ends returning all the file.

How can I define this line break on a string?


Thumbs up


Is the text file created explicitly with \r\n, or is it made with a text editor?
I generally don't bother with read_until, and just read the whole file and split it into an array with string_split. When it comes to unreliable linebreaks, I might use string_replace on the file text before splitting (ex, replace \r with \n, then just split around \n).
You then have to be sure you never try to reference a line past the end of the array, of course.

Some of my games
Keep up to date by following @Jeqofire on twitter!
Ear Ninja?

Thumbs up


I'm having serious bad times dealing with file parsing. Here's a link to this folder, inside it there's a fileparse.bgt which you will find to be a very very simple code, open a file in read mode, pass it's content to a string variable, then pass it to another file object then save it.

So, as you'll notice when you run it, the resulting new_spoiler.txt file is totally messed up with line breaks and line order.

Any insights welcome. I'll give the big picture so you can try to help me furthermore:

I'm playing with the idea of making a very simple Magic: the Gathering P2P client using BGT. I wrote a Card class with all the data structure I need, and I declared a dictionary where I intend to store all cards with a single numeric key for each one. This dictionary can then be serialized to a file and used in the Deck Editor.

First I went to Google and got this spoiler.txt file, which contains all cards from a specific edition. I'm starting with a few cards for testing, then I'll get the full card listing when the parser works. My idea was to declare a card object, then go inside a loop and parse properties to it, then send it to the dictionary and start over the loop. When it reaches end of file the deck dictionary should have one entry for each card and be ready to serialize.

Right now I'm stuck with parsing this spoiler.txt file, whether by read_until or by string_split, because it's totally messing up with line breaks.


Thumbs up


Ah, the link
https://www.dropbox.com/s/k2oyrl7y4qe06 … e.rar?dl=0

Thumbs up


Ok, old problem solved. The issue was around use of \r, \n or \r\n for line breaking. Now I have another problem with the parser.

https://www.dropbox.com/s/0p8i3gi8oly8f … r.rar?dl=0

As you can see, when you run main.bgt the script parses the file accordingly, storing each entry inside an object then each object inside a dictionary key. So far, so good, when I call the final number of elements in the dict it returns 350, just the right number.

But when I try to write this string into a file object to save it, it saves an empty string, as if serialize is returning nothing from a dictionary with 350 entries.

Can anyone find where's the mistake?


Thumbs up


You cannot simply serialize an object in BGT.
You need to write and call code to convert the object to a string or primitive (int, double, etc) before calling serialize. Any arbitrary objects in a dictionary to be serialized will be ignored.
Also, useful code to get you an array of strings from a file:

string[] readlines(string input)
//This function returns an array of strings matching the lines of a file.
file loader;
string [] lines(0);//array of lines to send back.
string processing;
alert("Error loading file","There was an error loading file "+input+". Please make sure that this file exists, and try again.");
return lines;

You may want to modify it in the case that you don't want a missing file to cause a fatal error, but that particular function is well worth setting aside somewhere so you can copy paste it into any project you like.
As an aside, in terms of performance, its vastly more efficient (think exponentially) to read the whole file and use string_split, rather than reading to a delimiter and processing line by line.

Thumbs up


Thanks a lot, dude, that really helped.

Best regards,

Thumbs up

8 (edited by Ethin 2017-09-27 02:11:25)

The problem with parsing text, especially if you've never written a parser before -- not some hodgepodge parser that parses strings only (that's not really a parser, just a scanner) -- is the fact that you've got to gather all the data into an array or some other form of memory storage and then tokenize it, discard all the data you don't need, then actually parse it. Parsing the tokenized data can be a right pain in the ass, especially in BGT. (Now, if you wrote it in something like Bison/YACC or hand-coded it yourself in C or C++ or any other programming language, it wouldn't be so difficult.) You can try and write a parser that actually parses something and doesn't just scan things -- but that actually parses things, produces errors and warnings, etc., and I wish you good luck with it. But I'm not going to put high bets on any success. But that's not your original query. You didn't -- and most likely still don't -- want to write a fully-blown micro-language -- you just want to parse text. To that end I'd recommend regular expressions. file.read_until doesn't use regular expression matching, so it's not going to let you do that. You'd either have to use a DLL (which, sadly, the DLL library is definitely not a very good implementation at all -- it's difficult to use and even the manual discourages you from using it) or write your own implementation in BGT of all your own.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.

Thumbs up