- 책 또는 웹사이트의 내용을 복제하여 다른 곳에 게시하는 것을 금지합니다.
- 책 또는 웹사이트의 내용을 발췌, 요약하여 강의 자료, 발표 자료, 블로그 포스팅 등으로 만드는 것을 금지합니다.
입출력 인터페이스 사용하기
이재홍 http://www.pyrasis.com 2014.12.17 ~ 2015.02.07
Go 언어는 io.Reader, io.Writer 인터페이스를 활용하여 다양한 방법으로 입출력을 할 수 있습니다. 즉, 입출력 인터페이스를 받는 여러 패키지가 있으므로 화면에 출력하는 부분부터 파일, 문자열까지 같은 인터페이스로 처리할 수 있습니다.
io.Reader와 io.Writer의 정의는 다음과 같습니다.
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
어떤 구조체든 매개변수로 바이트 슬라이스를 받고, 정수와 에러 값을 리턴하는 Read 함수를 가지고 있으면 io.Reader 인터페이스를 따른다고 할 수 있습니다. 마찬가지로 매개변수로 바이트 슬라이스를 받고 정수와 에러 값을 리턴하는 Write 함수를 가지고 있으면 io.Writer 인터페이스를 따른다고 할 수 있습니다.
파일 처리하기
다음은 bufio 패키지에서 제공하는 입출력 인터페이스 함수입니다.
- func NewReader(rd io.Reader) *Reader: io.Reader 인터페이스로 io.Reader 인터페이스 따르는 읽기 인스턴스 생성
- func NewWriter(w io.Writer) *Writer: io.Writer 인터페이스로 io.Writer 인터페이스를 따르는 쓰기 인스턴스 생성
- func (b *Writer) WriteString(s string) (int, error): 문자열을 버퍼에 저장
- func (b *Writer) Flush() error: 버퍼의 데이터를 파일에 저장
bufio는 Buffered I/O를 뜻하며 io.Reader, ioWriter 인터페이스를 받습니다. 이제 bufio를 사용하여 파일을 읽고 써보겠습니다.
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
file, err := os.OpenFile(
"hello.txt",
os.O_CREATE|os.O_RDWR|os.O_TRUNC, // 파일이 없으면 생성,
// 읽기/쓰기, 파일을 연 뒤 내용 삭제
os.FileMode(0644), // 파일 권한은 644
)
if err != nil {
fmt.Println(err)
return
}
defer file.Close() // main 함수가 끝나기 직전에 파일을 닫음
w := bufio.NewWriter(file) // io.Writer 인터페이스를 따르는 file로
// io.Writer 인터페이스를 따르는 쓰기 인스턴스 w 생성
w.WriteString("Hello, world!") // 쓰기 인스턴스로 버퍼에 Hello, world! 쓰기
w.Flush() // 버퍼의 내용을 파일에 저장
r := bufio.NewReader(file) // io.Reader 인터페이스를 따르는 file로
// io.Reader 인터페이스를 따르는 읽기 인스턴스 r 생성
fi, _ := file.Stat() // 파일 정보 구하기
b := make([]byte, fi.Size()) // 파일 크기만큼 바이트 슬라이스 생성
file.Seek(0, os.SEEK_SET) // 파일 읽기 위치를 파일의 맨 처음(0)으로 이동
r.Read(b) // 읽기 인스턴스로 파일의 내용을 읽어서 b에 저장
fmt.Println(string(b)) // 문자열로 변환하여 b의 내용 출력
}
bufio.NewWriter 함수에 file 인스턴스를 넣으면 io.Write 인스턴스를 따르는 쓰기 인스턴스를 리턴합니다(물론 file 인스턴스도 io.Writer 인터페이스를 따릅니다). 그리고 WriteString과 같은 메서드로 파일에 문자열을 저장할 수 있습니다. 단, bufio이므로 파일에 바로 저장하지 않고 임시 공간(버퍼)에 쌓아둡니다. 따라서 버퍼의 내용을 파일에 완전히 저장하려면 Flush 메서드를 사용합니다.
마찬가지로 bufio.NewReader 함수에 file 인스턴스를 넣으면 io.Reader 인터페이스를 따르는 읽기 인스턴스를 리턴합니다(file 인스턴스도 io.Reader 인터페이스도 따릅니다). 그리고 읽기 인스턴스로는 읽기 작업을 할 수 있습니다. 여기서 파일을 읽기 전에 file.Stat 함수로 파일 크기를 구해온 뒤 슬라이스를 생성합니다.
앞에서 먼저 WriteString 함수로 파일을 조작했으므로 파일 읽기/쓰기 위치(offset)가 이동하였습니다. 그러므로 file.Seek 함수로 offset을 초기화해 준 뒤 Read 메서드로 파일의 내용을 읽습니다.
매우 큰 파일을 읽을 때는 읽을 크기만큼의 슬라이스를 할당 한 뒤 file.Seek 함수로 읽을 위치를 옮겨가면서 일부만 읽으면 됩니다.
저작권 안내
이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.- 블로그, 게시판 등에 퍼가는 것을 금지합니다.
- 비공개 포스트에 퍼가는 것을 금지합니다.
- 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
- 링크 및 SNS 공유는 허용합니다.