방개
비밀번호를 잊어버리셨나요?

코드

[오토핫키] 전체 줄 읽어올 때 FileReadLine을 사용하면 안되는 이유

    • 글자 크기

FileReadLine은 특정 줄의 내용을 읽어올 수 있는 명령어입니다.

 

FileReadLine, OutputVar, Filename, lineNumber

위와 같이 쓰며, LineNumber에 쓴 줄을 Filename에 쓴 텍스트 파일에서 찾아 OutputVar로 출력해주는 역할을 합니다.

 

그런데, 간혹 "모든 줄 수를 읽어오는 데" 이 FileReadLine을 쓰는 분이 계십니다.

반복문 안에 넣어서 index 값을 LineNumber 값으로 주는 방식으로 말입니다.

 

즉, 아래와 같이요.

a := ""
Loop
{
    FileReadLine, var, test.txt, %A_index%
    a .= var "`n"
    if (ErrorLevel = 1) ;텍스트 파일의 끝을 읽어왔을 때 Break하기 위함
        Break
}
MsgBox, % a

네, a의 값엔 test.txt의 값이 순서대로 그대로 담기는 게 맞습니다. (사실 이렇게 쓰면 FileRead와 동일하지만, 이렇게 쓰시는 분들은 반복문 안에 "어떤 짓"을 따로 하시니까 반복문을 돌리신거겠지요.)

 

그런데 이는 굉장히 느린 방법입니다. 이럴 땐 Loop, Parse를 사용하는 것이 상상도 못할 정도로 빠릅니다.

특히 텍스트의 길이가 길어질수록 이 차이는 극심하게 나게 됩니다.

 

Loop,Parse는 특정 문자열을 기준으로 텍스트를 끊어주는 명령어입니다.

이 "특정 문자열"을 개행문자인 `n로 끊어주시면 FileReadLine과 동일한 역할을 하게 됩니다.

물론 FileRead를 먼저 해주어야겠지요. 아래처럼 쓰시면 Loop, Parse를 이용하여 위에서 했던 FileReadLine과 동일한 효과를 냅니다.

a := ""
FileRead, test, test.txt
Loop, Parse, test, `n
    a .= A_LoopField "`n"
MsgBox, % a

일단 줄 수도 짧아졌습니다. (사람마다 관점이 다르기에) 보기에는 더 깔끔한지 모르겠지만, 속도 차이는 심하게 납니다.

 

위의 두 코드로 10000줄짜리 텍스트 파일을 읽어와보겠습니다. 텍스트 파일엔 애국가 1절(4줄)이 2500번 들어있습니다.

 

SetBatchLines, -1
g := ""
startTime := A_TickCount
Loop
{
	FileReadLine, s, test.txt, %A_index%
	g .= A_LoopField "`n"
	if (errorlevel = 1)
		break
}
final := A_TickCount - StartTime
MsgBox, % final

텍스트 파일을 읽는 속도를 소숫점 세 자리까지 재봅니다. (A_TickCount는 소숫점 세 자리까지 보이기 때문입니다.)

먼저 위 코드는 FileReadLine을 사용한 방법입니다. (SetBatchLines를 사용하여 줄 간 딜레이를 없앴습니다.)

 

40.png

19.265초입니다. (다시한번 말씀드리지만 10000줄짜리 txt파일입니다.)

 

이제 Loop, Parse를 사용해보겠습니다.

SetBatchLines, -1
g := ""
startTime := A_TickCount
FileRead, test, test.txt
Loop, Parse, test, `n
	g .= A_LoopField "`n"
final := A_TickCount - StartTime
MsgBox, % final

42.png

0.094초입니다.

 

변수에 값을 담는데만 해도 이정도 속도차이가 납니다.

혹시 변수에 값이 안들어갔나 생각해봐서 변수도 출력해보았습니다.

44.png

잘나옵니다.

 

10000줄짜리 텍스트를 그대로 변수에 한줄씩 따로 담아오는 데 걸리는 시간이

19.265초와 0.094초입니다.

단순 계산으로는 약 204배가 더 빠르네요.

 

줄 수에 비례하여 더욱 차이가 나기 때문에, FileReadLine은 텍스트파일 전체를 한 줄씩 읽어올때 쓰지 마셔야 합니다.

특정 줄, 딱 한 줄 읽어오실 때만 FileReadLine을 사용해주세요.

 

 

오늘의 결론.

Loop, Parse는 쓸 수 있으면 쓰자.

    • 글자 크기
댓글 7
  • 방개글쓴이
    2019.10.5 23:46 댓글

    추가) 명령어 까보면 FileReadLine은 FileRead가 포함되어있습니다. 여러분이 FileReadLine을 반목문에 줄 수만큼 돌리면, 오토핫키는 FileRead를 줄 수만큼(!!) 하게 됩니다. 여기서부터 속도차이가 벌어지는 것이지요.

  • 2019.10.6 12:14 댓글

    오 대꿀잼이에요! 이런거 자주 올려주시면 제 군생도 빨리 녹지 않을까요 흑

  • 생활관_처돌이님께
    방개글쓴이
    2019.10.6 13:05 댓글

    앗아아.. 파이팅입니다

  • 방개님께
    2019.10.6 14:11 댓글

    ㅎㅎ.. 감사합니다~

  • 2020.7.16 17:19 댓글

    오... 그동안 짰던 소스들 확인해보니, FileRead만 사용해 왔네요. 다행...

     

    특정 라인을 위한 FileReadLine과 FileRead의 차이점, Loop,Parse

    그리고 속도차이를 확인 하는법에 대해서 배워갑니다.

     

    좋은 글 감사합니다.

  • 2020.10.27 20:28 댓글

    test.txt 의 내용이 20201025 한줄 뿐입니다.

    이걸 FileRead aaa , test. txt

    로 읽어 와서 줄바꿈이 포함 되어 있는데, 이 줄바꿈을 없앨려면 어찌 하나요?

    예시)

    FileRead aaa , test. txt

    zzz = %aaa%

    qqq := zzz "New_AppData.MB"

    MsgBox, %zzz%%qqq%

     

    결과값 20201025

    New_AppData.MB

    이렇게 둘줄로 나와요...

     

    이걸 20201025New_AppData.MB

    이렇게 한줄로 나오게 할 때 CR+LF 를 없애야 할 듯 한데...........어찌 하는지요???

     

     

     

  • 에바다님께
    프날글쓴이
    2020.10.28 15:59 댓글

    그냥 SubStr을 이용해서 맨 뒤에 한 글자를 제거해봅시다.

댓글 달기

서버에 요청 중입니다. 잠시만 기다려 주십시오...