IOError

IOError

IO 연산이 실패할 때 발생하는 예외예요. StandardError를 상속받는 예외 클래스고, 추가로 정의된 메서드는 없어요.

출처: Ruby 4.0 API

본문

IO에 관련된 작업을 하다 보면 "이 스트림을 지금 쓰거나 읽을 수 없는 상황"을 만날 때가 있어요. 그럴 때 Ruby가 던지는 예외가 바로 IOError예요. 쓰기 전용으로 열지 않은 파일에 쓰려고 하거나, 이미 닫힌 스트림에서 읽으려고 할 때가 대표적이죠.

File.open("/etc/hosts") {|f| f << "example"}
  #=> IOError: not opened for writing

File.open("/etc/hosts") {|f| f.close; f.read }
  #=> IOError: closed stream

첫 번째 예시는 읽기 모드로 연 파일에 <<로 쓰려다 실패한 경우고, 두 번째는 close로 닫아버린 스트림에서 read를 호출한 경우예요. 둘 다 "지금 이 연산은 스트림 상태에서 허용되지 않는다"는 의미로 IOError가 나요.

한 가지 짚고 넘어갈 점이 있어요. 모든 IO 실패가 IOError로 오는 건 아니에요. 파일 자체가 없다거나 권한이 없다거나 하는 시스템 레벨 실패는 SystemCallError(Errno::*) 계열로 오고, 이들은 IOError의 하위 클래스가 아니에요.

File.open("does/not/exist")
  #=> Errno::ENOENT: No such file or directory - does/not/exist

does/not/exist라는 파일이 없으니 "요소가 없습니다(ENOENT)"라는 시스템 에러가 나는 게 보이죠. 곧 파일이 없어서 실패하는 건 IOError가 아니라 Errno::ENOENT라는 걸 기억해 두면, 예외를 받아 처리할 때 어느 계열로 잡을지 헷갈리지 않아요.