Notifications
Clear all

[Closed] stringStream Backwards

I need to read a stringStream Backwards line by line, someone knows how? I’m getting crazy with this…

thanks in advance.

10 Replies

You could read it forwards, line by line, store each line as elements of an array, and then loop through the array backwards ?

The problem is that i’m trying to read it backwards because i need to reach a value that is about the end of a file with hundred of thousands of lines. The time i spend reading line by line is too long so i would like to do it from the end.

thanks anyway for the reply

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

in my experience always better to use skipToString method then read fileStream or StringStream lines in backward order…


(
ss -- stringStream
sub -- searching substring
if (p = skipToString ss sub) != undefined do
(
str = sub + (readline ss) -- searching string 
)
)
 

it’s a fastest way…

an easy solution for this, and not the optimal, could be to filter the string using ‘filterString’
with the new line char as the filter “
“,
then you have an array of lines and you can loop through it backwards with


for i = filteredLines.count to 1 by -1 do
    ...

thanks, i’ll try it.

I’ve found a way that is faster tahn skipToString, in the case yo know that the string you want to search is near the end of the file.

(
	fileName = "C:\\asdf\\asdf\\asdf.extension"
	
	startTime = timeStamp()
	
	f = openFile fileName mode:"r"
	maxlen = 0
	
	if f != undefined then --if file is correctly opened
	(
		seek f #eof
		maxlen = filepos f
		
		aux = 0
		stop = false

		i = 1
		while not stop and i < maxlen do--maxlen do
		(
			seek f (maxlen - i - aux)
			char = readChar f
			if (char == "
") then
			(
				if (i==1) then seek f (maxlen - i - aux)
				currentLine = (readLine f)
				aux = 1
				
				if findString currentLine "stringToFind" != undefined then
				(
					stop = true
					seek f (maxlen - i - aux)

					endTime = timeStamp()
					print ((endTime - startTime)/1000.0)
				)
			)
			else
				aux = 0
			
			if (maxlen - i) == 0 then
				stop = true
			
			i+= 1
		)
	
		close f
	)
	
	endTime = timeStamp()	
	print ((endTime - startTime)/1000.0)
	print "-----------------"

)
1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

it only works in very special cases. It can’t be faster in common case because read by char is much slower then read by line. Check the sample that I made:


fn createSkipFile len:200000 pos:0.85 = 
(
 if not (doesfileexist "c:/temp") do makeDir "c:/temp"
 file = "c:/temp/skipfile.txt"
 index = len*pos
 if (ss = createfile file) != undefined do
 (
  other = "\"Everything takes longer than it takes.\" (Jon Carpenter)"
  for i=1 to len do
  (
   format "%
" (if i == index then "String To Find --------------------> is Here" else other) to:ss
  )
  flush ss
  close ss
--  edit file
 )
)
fn forwardSkipString sub:"String To Find" =
(
 t1 = timestamp()
 if doesfileexist (file = "c:/temp/skipfile.txt") and (ss = openfile file) != undefined do
 (
  if (p = skipToString ss sub) != undefined do
  (
   str = sub + (readline ss) -- searching string 
  )
  flush ss
  close ss
 )
 format "done: % %
" ((timestamp() - t1)/1000.) str
 str
)
fn backwardSkipString sub:"String To Find" =
(
 t1 = timestamp()
 if doesfileexist (file = "c:/temp/skipfile.txt") and (ss = openfile file) != undefined do
 (
  seek ss #eof
  maxlen = filepos ss
  
  aux = 0
  stop = false
  i = 1
  while not stop and i < maxlen do
  (
   seek ss (maxlen - i - aux)
   char = readChar ss
   if (char == "
") then
   (
	if (i==1) do seek ss (maxlen - i - aux)
	str = readLine ss
	aux = 1
	
	if findString str sub != undefined do
	(
	 stop = true
	 seek ss (maxlen - i - aux)
	)
   )
   else aux = 0
   
   if (maxlen - i) == 0 then stop = true
   
   i+= 1
  )
  if not stop do str = undefined
  flush ss
  close ss
 )
 format "done: % %
" ((timestamp() - t1)/1000.) str
 str
)


i’m making 200000 lines file with “string to find” in 85% position of it. If you set the string in 70% e.g. the difference between forward and backward methods will be huge!

Yes you are right at all, but i was trying to find my way because i have files of hundreds of thousand lines and i know the information i’m looking for is about at 99% of it. In most cases this information is in the last 100 lines, so i’ll use my method this time, but i’ll keep in mind “skipToString” for the general cases.

Thank you for your reply again, and for your time.

you can modify forward search using skipping part of file


fn forwardSkipString sub:"String To Find" skip:0.9 =
(
 t1 = timestamp()
 if doesfileexist (file = "c:/temp/skipfile.txt") and (ss = openfile file) != undefined do
 (
  if skip != unsupplied do
  (
   seek ss ((getfilesize file)*skip)
  )
  if (p = skipToString ss sub) != undefined do
  (
   str = sub + (readline ss) -- searching string 
  )
  flush ss
  close ss
 )
 format "done: % %
" ((timestamp() - t1)/1000.) str
 str
)


You are right again, I didn’t noticed this yesterday!, thanks.