Reading a random line from a file?
Blitz3D Forums/Blitz3D Beginners Area/Reading a random line from a file?
| ||
How can I read a random line from a file? Additionally, when reading files, will an endline character be read into my string like with gets() in PHP? If so is there a B3D equivalent to PHP's trim()? Thanks for your time. |
| ||
1. Probably easiest to read the entire file into an array, then pick a random one from there. 2. Yes. BRL in all their wisdom/cunning, chose to call it Trim(). ;) |
| ||
What if the file is rather large? I'm reading a wordlist for a hangman game, right now I have about 5000 words. Naturally, they're all strings so can I just repeatedly use ReadString()? Will it go down one live every time I do like fgets()? Basically, I just want to know if there is a B3D equivalent to fgets() Thank you for your previous answer. |
| ||
Don't use ReadString(), as it reads Blitz strings - a four-byte integer containing the number of characters, and then the characters themselves, without any kind of terminator. This is not really useful for reading plain text files. You can however just repeatedly use ReadLine(), which reads characters from the current position into a string until it hits the CRLF (newline) terminator, so it's much more helpful for reading normal text files. The newline itself isn't added to the string - Blitz strings don't have terminators at all - and the file pointer will move to the start of the next line, so it's all very convenient. There isn't a direct equivalent to fgets(), but you could write one pretty easily using ReadByte() if you really wanted to. I'd suggest using ReadLine() if you want to read from a text file. |
| ||
Groovy, thanks Yasha, I'll try it and see how things go. |
| ||
Does anyone know of a way to determine the number of lines in a file? |
| ||
To random a line, juste feed the filepos ( according to the file size previously "grabbed" on loading the stream ) like : MyFile=ReadFile("Your File") Size=FileSize("Your File") SeekPos(MyFile,rand(Size)) Then you read a first line to go to the next "full" line and you can return this random line using ReadLine() again. there is 2 ways ( and probably some others ) to get the line count : +> While not(eof(file)) Count=Count+1 Readline(file) Wend or count the number of LineFeed char (use ReadByte to get them )... but it may be long ^^ while not(eof(file)) if readbyte(file)=10 then Count=Count+1 Wend |
| ||
What if the file is rather large? Buzzword has a dictionary of something like 180,000 words and that's loaded in its entirety. The amount of resources overhead is surprisingly small, only a couple of MB. I'm reading a wordlist for a hangman game, right now I have about 5000 words |
| ||
Bear in mind the code is 'untested' - getting it to actually work may take further study but - Parse the file first (just as bobsait says) and index the data start positions returned by the readline function. Function IndexFile(FileName$,FileNum=False) If FileNum=False FileNum=OpenFile(FileName) Closure=True End If IndexBank=CreateBank(FileSize(FileName)) While Not(Eof(file)) PokeInt IndexBank,False,PeekInt(IndexBank,False)+1 PokePos=PeekInt(IndexBank,False)*4 If PokePos>BankSize(IndexBank) ResizeBank BankSize(IndexBank)+1024 End If PokeInt IndexBank,PokePos,SeekPos(FileNum) DataString$=ReadLine(FileNum) Wend ResizeBank IndexBank,PokePos+4 If Closure CloseFile FileNum End If Return IndexBank End Function Then you can return a random line quickly Function RandomLine$(IndexBank,FileNum) LineNo=Rnd(1,PeekInt(IndexBank,False) SeekPos FileNum,PeekInt(IndexBank,Rnd(1,LineNo))*4 DataString$=ReadLine(FileNum) Return DataString End Function |