본문으로 바로가기

bonkora 님이 제공해 주신 글입니다.


텍스트파일을 읽고 쓰는 작업에 대해 알아보기로 합니다. 사전 프로그램을 예로 들면, 자료의 크기가 작을 경우 자료전체를 메모리로 읽어 들여서 사용자가 필요로 하는 자료를 보여주는 게 효율적일 것입니다. 이런 것이 순차적 접근(sequential access)으로 읽는 방법이라 할 수 있겠죠. 만약 자료가 크다면 한꺼번에 메모리로 읽어 들이는 방법보다는 파일 내에서 자료들이 있는 위치와 크기만을 기억하고 있다가 필요시 그 자료 부분만을 읽어서 사용자에게 보여주는 방법이 더 나을 것입니다. 이것이 임의적 접근(random access)이 되겠습니다.

순차적 접근

먼저 텍스트파일을 읽어서 콘솔 상에서 출력시키는 코드를 만들어 봅니다. 에러발생은 편의상 고려하지 않습니다. 설명은 주석에 달았습니다.

# 파일을 열고 파일을 위한 채널 ID를 변수 f에 넣습니다
# "r"은 읽기를 목적으로 한다는 뜻입니다
set f [open srcfile.txt r]
# 연 파일에서 gets 명령으로 한 줄을 읽어서 변수 buffer에 저장합니다
set buffer [gets $f]
# eof는 파일의 끝인지를 질의하는 명령입니다
# 파일의 끝에 도달하기 전까지 계속 반복작업합니다.
while {![eof $f]} {
#   읽은 행을 콘솔에 출력합니다
    puts $buffer
#   한 줄의 텍스트를 읽어들입니다
    set buffer [gets $f]
}
# 파일을 닫습니다
close $f

이번엔 소스파일에서 한 줄씩 읽어 타깃파일에 써서 텍스트 파일을 복사하는 코드를 작성합니다.

set f1 [open srcfile.txt r]
# 쓰기를 위하여 파일을 연다
set f2 [open tgtfile.txt w]
set buffer [gets $f1]
while {![eof $f1]} {
#   파일에 한 행을 씁니다
    puts $f2 $buffer
    set buffer [gets $f1]
}
close $f1
close $f2

한 글자씩 읽어서 쓰는 경우에는 이렇게 합니다. 지정한 바이트만큼을 읽을 때엔 read 명령을 씁니다.

set f1 [open srcfile.txt r]
set f2 [open tgtfile.txt w]
# 한 글자를 읽어 변수 buffer에 저장합니다
set buffer [read $f1 1]
while {![eof $f1]} {
#   파일에 한 글자를 씁니다
#   한 글자 뒤에 줄바꿈 문자를 넣지 않기 위해 "-nonewline" 옵션을 붙입니다
    puts -nonewline $f2 $buffer
#   한 글자를 읽습니다
    set buffer [read $f1 1]
}
close $f1
close $f2

임의적 접근

작업을 위해 파일을 열면 이 파일은 파일의 내용에 대한 접근위치(access location)를 갖는데 이는 작업이 이루어질 위치를
말하는 것입니다. 그 위치는 파일의 첫 부분으로부터 몇 바이트 떨어져 있나로 표시하는 옵셋(offset)으로 나타냅니다. 파일을 처음 열었을 때 위치가 옵셋값 0에 있으며 작업에 따라 이동합니다.

아래의 코드는 텍스트파일의 각 행의 첫머리의 옵셋값을 구합니다. 텍스트파일을 읽어 들이면서 파일 내에서의 각 행의 첫 글자의 위치를 리스트 offset에 저장합니다. 파일의 접근위치의 옵셋값을 알아내는데 tell 명령을 씁니다.

set f [open srcfile.txt r]
# 옵셋값을 저장할 리스트 offsets를 만듭니다
set offsets {}
# tell 명령으로 알아낸 옵셋값을 리스트 offsets에 덧붙입니다
lappend offsets [tell $f]
set buffer [gets $f]
while {![eof $f]} {
    puts $buffer
    lappend offsets [tell $f]
    set buffer [gets $f]
}
close $f
puts $offsets

이렇게 하면 리스트 offsets엔 옵셋값들이 저장되는데 가장 마지막 요소는 파일 끝의 옵셋값이 되며 이는 곧 그 파일의 크기와 같습니다.

원하는 옵셋의 위치에 바로 접근하려면 seek 명령을 사용합니다. 아래는 파일을 열고 옵셋 100에 바로 가서 한 행의 텍스트를 읽는 코드의 예입니다. 파일 가장 첫머리의 옵셋값이 0인 것에 주의하십시오.

set f [open srcfile.txt r]
# 연 파일의 접근위치를 옵셋 100으로 옮긴다
seek $f 100
set buffer [gets $f]
puts $buffer
close $f