How to read specific line from file?

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
User avatar
Coderooney
Posts: 46
Joined: 23 Mar 2017, 22:41

How to read specific line from file?

15 Oct 2019, 00:38

This was the syntax to read the third line of a file in v1:

Code: Select all

FileReadLine, line, "file.txt", 3
How do we do the same in v2? The v2 docs don't seem to show a way to specify a line number: https://lexikos.github.io/v2/docs/objects/File.htm#ReadLine
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: How to read specific line from file?

15 Oct 2019, 01:49

filereadline has been deleted

Code: Select all

Line := StrSplit(FileRead('thefile.txt'), '`n', '`r')
Line[3] then contains ur line
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: How to read specific line from file?

15 Oct 2019, 02:22

Code: Select all

MsgBox(FileReadLine(FileSelect(),InputBox()))

FileReadLine(Filename, LineNum)
{
    local File := FileOpen(Filename, "r-wd")

    if (LineNum < 0)
    {
        local Pos   := File.Pos
        local Lines := 0
        while (!File.AtEOF)
            ++Lines, File.ReadLine()
        LineNum := Lines - Abs(LineNum) + 1
        File.Seek(Pos)
    }

    while (!File.AtEOF)
    {
        if (A_Index == LineNum)
            return File.ReadLine()
        File.ReadLine()
    }

    throw
}
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: How to read specific line from file?

15 Oct 2019, 07:03

- It's because of the verboseness(/possible additional resource use) of the alternatives, that I had thought that maybe FileReadLine should be brought back.
- People might be using it inefficiently to read multiple lines, (the possible rationale for removing it,) but if you do want just one line, it's useful.
- E.g. I could imagine wanting to read one of the first 5 lines of a file say.
- If we improved the functionality, by having -1 return the last line, -n the nth-to-last line etc, that could be quite good. You could have a further parameter to get n lines (starting at the stated line). (And, worth a mention: an options parameter to ignore blank lines, e.g. 'B' means that -1 gives the last non-blank line, ignoring any blank lines.)
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: How to read specific line from file?

20 Oct 2019, 13:53

"if u do the thing X was meant to do, X is useful"
it was removed because it is a very niche function that many had the propensity to misuse, some - downright abuse. glad its gone

-1 and nth to last u can already do with the array u get back from StrSplit newlines
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: How to read specific line from file?

20 Oct 2019, 15:18

- I already considered all the points you made, but I think there are stronger points to consider.

- It's quite common for people to want to retrieve the first/last n (non-blank) lines from a string/file. There have been frequent questions about it. And other things like remove/insert lines.

- Strings are fiddly: line n is between line breaks n-1 and n. Complications include: handling the last line, and multiple line break possibilities (e.g. CRLFs/CRs). Fiddly use of InStr and SubStr is required.
- Arrays are less fiddly, but you have to create an array of lines for the entire file which is very inefficient. Arrays can still be relatively complex for newbies.
- So, potentially, in line with the AHK ethos, you could have: get lines from file function (expanded FileReadLine), and an equivalent get lines from string function. (I would perhaps require set line text, insert line(s), remove line(s) etc be done via arrays.) A StrJoin function would help to stitch the lines back together.

- Using FileReadLine multiple times to read lines is 'misuse', but so is FileRead/StrSplit on a large text file, where FileReadLine would be better.
- FileRead and StrSplit can be very inefficient, one of the key reasons I felt FileReadLine should stay:

Code: Select all

;AHK v1

q:: ;create large text file
vLen := 18
vLine := SubStr("abcdefghijklmnopqrstuvwxyz", 1, vLen)
VarSetCapacity(vOutput, 20000000*2)
Loop % 10000000/(vLen+2)
	vOutput .= vLine "`r`n"
vPath := A_Desktop "\z test 10MB text.txt"
if !FileExist(vPath)
	FileAppend, % vOutput, % "*" vPath, UTF-8
return

w:: ;read line from large text file
vPath := A_Desktop "\z test 10MB text.txt"

vNum := 100

vTickCount1 := A_TickCount
Loop % vNum
	FileReadLine, vText, % vPath, 3
vTickCount2 := A_TickCount
MsgBox, % vText
Clipboard .= "`r`n" (vTickCount2-vTickCount1)

vTickCount1 := A_TickCount
Loop % vNum
{
	FileRead, vText, % vPath
	vText2 := StrSplit(vText, "`n", "`r")[3]
}
vTickCount2 := A_TickCount
MsgBox, % vText2
Clipboard .= "`r`n" (vTickCount2-vTickCount1)
return

;some results (msec):
;FileReadLine FileRead/StrSplit
;16 11232
;16 11185
;0 11123
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: zed6250jb and 26 guests