Reading a random line from a file?

Blitz3D Forums/Blitz3D Beginners Area/Reading a random line from a file?

zortzblatz(Posted 2009) [#1]
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.


GfK(Posted 2009) [#2]
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(). ;)


zortzblatz(Posted 2009) [#3]
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.


Yasha(Posted 2009) [#4]
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.


zortzblatz(Posted 2009) [#5]
Groovy, thanks Yasha, I'll try it and see how things go.


zortzblatz(Posted 2009) [#6]
Does anyone know of a way to determine the number of lines in a file?


Bobysait(Posted 2009) [#7]
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


GfK(Posted 2009) [#8]
What if the file is rather large?

I'm reading a wordlist for a hangman game, right now I have about 5000 words
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.


Graythe(Posted 2009) [#9]
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