IO

IO

운영체제의 입출력 스트림(input/output stream)을 나타내는 클래스예요. Ruby 입출력의 기반이 되는 클래스랍니다.

출처: Ruby 3.3 API

본문

클래스 IO의 인스턴스(보통 스트림이라 불러요)는 운영체제의 입출력 스트림을 나타내요. 클래스 File은 Ruby 코어에서 IO의 유일한 서브클래스이고, 표준 라이브러리의 TCPSocket, UDPSocket도 IO의 서브클래스예요.

전역 상수 ARGF($<로도 접근)는 ARGV(비어 있으면 STDIN)의 모든 파일 경로에 접근할 수 있는 IO 같은 스트림을 제공해요. 클래스 StringIO는 String을 다루는 IO 같은 스트림이에요. 둘 다 IO의 서브클래스는 아니에요.

IO 기반의 중요한 객체들: $stdin, $stdout, $stderr, File 인스턴스.

IO 인스턴스는 다음으로 만들 수 있어요:

  • IO.new — 주어진 정수 파일 디스크립터로 새 IO 객체
  • IO.open — 새 IO 객체를 블록에 넘김
  • IO.popen — 새로 시작된 서브프로세스의 $stdin·$stdout에 연결된 새 IO 객체
  • Kernel#open — 주어진 소스(스트림·파일·서브프로세스)에 연결된 새 IO 객체

File 스트림처럼 IO 스트림은 다음을 가져요:

  • 읽기/쓰기 모드(읽기 전용·쓰기 전용·읽기/쓰기)
  • 데이터 모드(텍스트 전용·바이너리)
  • 내부·외부 인코딩
  • 위치(position) — 다음 읽기·쓰기가 일어날 스트림 내 위치
  • 줄 번호(line number) — 줄 단위의 특별한 "위치"

확장 io/console

io/console 확장은 콘솔과 상호작용하는 많은 메서드를 제공해요. 이걸 require하면 클래스 IO에 여러 메서드가 추가돼요.

열기 옵션 (Open Options)

여러 IO 메서드는 새 스트림을 어떻게 열지 결정하는 선택 키워드 인자를 받아요:

  • :mode — 스트림 모드
  • :flags — 정수 파일 열기 플래그 (mode와 함께 주면 bitwise OR)
  • :external_encoding — 외부 인코딩
  • :internal_encoding — 내부 인코딩 ('-'는 기본 내부 인코딩의 동의어, nil이면 변환 안 함)
  • :encoding'extern:intern' 형태로 외부·내부 인코딩 지정
  • :textmode — 참이면 텍스트 전용, 그 외엔 바이너리
  • :binmode — 참이면 바이너리, 그 외엔 텍스트 전용
  • :autoclose — 참이면 스트림이 닫힐 때 fd도 닫힘
  • :path — inspect에 사용되고 path 메서드로 접근할 수 있는 문자열

String#encode에서 제공하는 옵션도 사용 가능한데, 외부·내부 인코딩 간 변환을 제어해요.

기본 IO (Basic IO)

보통 멀티바이트 문자열에 작동하는 기본 스트림 IO 메서드:

  • IO#read — 스트림에서 남은 바이트의 일부 또는 전부를 읽어 돌려줘요.
  • IO#write — 스트림에 문자열 0개 이상을 써요 (문자열이 아닌 객체는 to_s로 변환).

위치 (Position)

IO 스트림에는 음이 아닌 정수 위치(다음 읽기·쓰기가 일어날 바이트 오프셋)가 있어요. 새 스트림은 위치 0(줄 번호 0)이고, rewind가 위치·줄 번호를 0으로 되돌려요. 관련 메서드:

  • IO#tell(별칭 #pos) — 현재 위치(바이트) 반환
  • IO#pos= — 스트림 위치를 주어진 정수로 설정
  • IO#seek — 주어진 기준점(시작·끝·현재)에서 주어진 바이트만큼 이동
  • IO#rewind — 스트림을 처음으로(줄 번호도 초기화)

열림/닫힘 (Open and Closed Streams)

새 IO 스트림은 읽기용·쓰기용·둘 다로 열릴 수 있어요. 가비지 컬렉터가 소유하면 자동으로 닫혀요. 닫힌 스트림에서 읽기·쓰기는 예외를 일으켜요. 관련 메서드: IO#close, IO#close_read, IO#close_write, IO#closed?.

스트림 끝 (End-of-Stream)

IO#eof?(별칭 #eof)는 스트림이 끝에 있는지 돌려줘요. IO#seek로 끝으로 이동하거나 스트림 내용을 전부 읽어 끝에 도달할 수 있어요.

줄 IO (Line IO)

스트림을 줄 단위로 읽는 메서드: IO#each_line, IO#gets, IO#readline(끝에서 예외), IO#readlines. 각 메서드는 선택 줄 구분자 sep와 줄 길이 제한 limit를 받아요. 스트림 위치에 따라 줄 중간부터 읽힐 수도 있어요. 줄 단위 쓰기는 IO#puts.

줄 구분자 (Line Separator)

기본 줄 구분자는 전역 변수 $/(기본 "\n"). 다음에 읽힐 줄은 현재 위치부터 다음 줄 구분자까지의 데이터예요. 특별한 구분자 두 가지가 있어요:

  • nil — 스트림 전체를 하나의 문자열로 읽음
  • ''(빈 문자열) — 다음 "문단"(연속된 두 줄 구분자로 구분)을 읽음

줄 길이 제한 (Line Limit)

반환되는 바이트 수가 주어진 limit보다 (많이) 길지 않도록 해요. 멀티바이트 문자는 쪼개지지 않으므로 줄이 제한보다 약간 길 수 있어요. limit가 없으면 sep로만 결정돼요.

줄 번호 (Line Number)

읽기 가능한 IO 스트림은 음이 아닌 정수 줄 번호를 가져요. IO#lineno·IO#lineno=가 관련 메서드예요. foreach, each_line, gets, readline, readlines는 줄을 읽을 때마다 줄 번호를 증가시켜요. 스트림 위치와 달리 줄 번호는 다음 읽기·쓰기가 일어날 곳엔 영향이 없어요. 전역 변수 $.는 마지막으로 읽은 스트림의 줄 번호와 연관돼요.

문자 IO (Character IO)

문자 단위 처리: IO#getc, IO#readchar(끝에서 예외), IO#ungetc, IO#putc, IO#each_char.

바이트 IO (Byte IO)

바이트 단위 처리: IO#getbyte, IO#readbyte(끝에서 예외), IO#ungetbyte, IO#each_byte.

코드포인트 IO (Codepoint IO)

IO#each_codepoint — 남은 각 코드포인트를 블록에 넘겨요.

여기 있는 것 (What's Here)

클래스 IO는 Object에서 상속받고 Enumerable 모듈을 포함해요. 여기서 IO는 다음을 위한 메서드를 제공해요:

  • 만들기: ::new(별칭 ::for_fd), ::open, ::pipe, ::popen, ::select
  • 읽기: ::binread, ::read, ::readlines, getbyte, getc, gets, pread, read, read_nonblock, readbyte, readchar, readline, readlines, readpartial
  • 쓰기: ::binwrite, ::write, <<, print, printf, putc, puts, pwrite, write, write_nonblock
  • 위치: lineno, lineno=, pos(별칭 tell), pos=, reopen, rewind, seek
  • 순회: ::foreach, each(별칭 each_line), each_byte, each_char, each_codepoint
  • 설정: autoclose=, binmode, close, close_on_exec=, close_read, close_write, set_encoding, set_encoding_by_bom, sync=
  • 조회: autoclose?, binmode?, close_on_exec?, closed?, eof?(별칭 eof), external_encoding, fileno(별칭 to_i), internal_encoding, pid, stat, sync, tty?(별칭 isatty)
  • 버퍼링: fdatasync, flush, fsync, ungetbyte, ungetc
  • 저수준 접근: ::sysopen, advise, fcntl, ioctl, sysread, sysseek, syswrite
  • 기타: ::copy_stream, ::try_convert, inspect

상수 (Constants)

  • EWOULDBLOCKWaitReadable / EWOULDBLOCKWaitWritableIO::EAGAINWaitReadable/WaitWritable와 동일
  • PRIORITY, READABLE, WRITABLEIO#wait용 이벤트 마스크
  • SEEK_CUR, SEEK_DATA, SEEK_END, SEEK_HOLE, SEEK_SET — seek 기준점 상수

더 알아보기: 공개 클래스 메서드 (Public Class Methods)

binread(path, length = nil, offset = 0) → string or nil

IO.read와 같되 스트림을 ASCII-8BIT 인코딩의 바이너리 모드로 열어요. 신뢰할 수 없는 입력 주의(Command Injection).

binwrite(path, string, offset = 0) → integer

IO.write와 같되 바이너리 모드(ASCII-8BIT)로 열어요. 신뢰할 수 없는 입력 주의(Command Injection).

console → #<File:/dev/tty>

열린 콘솔의 File 인스턴스를 돌려줘요. sym이 주어지면 열린 콘솔에 args와 함께 보내고 그 결과를 돌려줘요. require 'io/console' 필요.

copy_stream(src, dst, src_length = nil, src_offset = 0) → integer

주어진 src에서 dst로 복사하고 복사된 바이트 수를 돌려줘요. src는 읽을 수 있는 파일 경로 또는 :readpartial/:read에 응답하는 IO 같은 객체, dst는 쓸 수 있는 파일 경로 또는 :write에 응답하는 IO 같은 객체예요. src_length로 최대 바이트를, src_offset로 읽기 시작 오프셋을 지정할 수 있어요.

IO.copy_stream('t.txt', 't.tmp')  # => 47
IO.copy_stream('t.txt', 't.tmp', 10) # => 10
IO.copy_stream('t.txt', 't.tmp', 11, 11) # => 11

for_fd(fd, mode = 'r', **opts) → io

IO.new의 동의어예요.

foreach(path, sep = $/, **opts) {|line| block } → nil

파일의 각 줄로 블록을 호출해요. sep·limit·''(문단)·nil(전체) 등을 지원해요. 블록이 없으면 Enumerator를 돌려줘요. 신뢰할 수 없는 입력 주의(Command Injection).

new(fd, mode = 'r', **opts) → io

파일 디스크립터에서 새 IO 객체(파일 스트림)를 만들어 돌려줘요. fd는 유효한 정수 파일 디스크립터여야 해요. 저수준 라이브러리와 상호작용에 유용하고, 더 간단한 상호작용은 File.open이 좋아요.

path = 't.tmp'
fd = IO.sysopen(path) # => 3
IO.new(fd)            # => #<IO:fd 3>

새 IO 객체는 인코딩을 상속하지 않아요. mode는 유효한 IO 모드여야 해요.

open(fd, mode = 'r', **opts) → io

IO.new로 새 IO 객체를 만들어요. 블록이 없으면 IO 객체를, 블록이 있으면 그 값을 돌려줘요.

pipe(**opts) → [read_io, write_io]

서로 연결된 파이프 끝 read_io·write_io 쌍을 만들어요. 인코딩을 지정할 수 있어요. 블록이 없으면 두 끝을 배열로, 블록이 있으면 블록에 넘기고 양 끝을 닫은 뒤 블록 값을 돌려줘요. 모든 플랫폼에서 가능한 건 아니에요. 파이프의 읽기 끝은 쓰는 쪽이 열려 있으면 EOF 조건을 만들지 않아요.

rd, wr = IO.pipe
if fork
  wr.close
  puts "Parent got: <#{rd.read}>"
  rd.close
  Process.wait
else
  rd.close
  puts 'Sending message to parent'
  wr.write "Hi Dad"
  wr.close
end

popen(env = {}, cmd, mode = 'r', **opts) → io

명령 cmd를 서브프로세스로 실행하고, 그 $stdin·$stdout을 새 스트림 io에 연결해요. 신뢰할 수 없는 입력 주의(Command Injection). 블록이 없으면 스트림을 돌려주고(나중에 명시적으로 닫아야 리소스 누수를 피해요), 블록이 있으면 스트림을 넘기고 종료 시 닫은 뒤 블록 값을 $?에 할당하고 돌려줘요. cmd에 따라 다음이 발생해요:

  • '-' — 프로세스 fork
  • 단일 문자열 — 셸에서 실행
  • 문자열 배열 — cmd[0] 프로그램을 인자들과 함께 실행
  • 첫 요소가 2-요소 문자열 배열 — argv0까지 지정
IO.popen('-') do |pipe|
  if pipe
    $stderr.puts "In parent, child pid is #{pipe.pid}"
  else
    $stderr.puts "In child, pid is #{$$}"
  end
end

IO.popen('uname') do |pipe|
  pipe.readlines
end

IO.popen([['/bin/sh', 'foo'], '-c', 'echo $0']).read # => "foo\n"

read(path, length = nil, offset = 0, **opts) → string or nil

스트림을 열고 내용의 일부·전부를 읽어 닫아요. 읽은 바이트가 없으면 nil. length·offset으로 범위를 지정할 수 있어요.

IO.read('t.txt')
# => "First line\nSecond line\n\nThird line\nFourth line\n"
IO.read('t.txt', 7)   # => "First l"
IO.read('t.txt', 10, 2)   # => "rst line\nS"
IO.read('t.txt', 10, 200) # => nil

신뢰할 수 없는 입력 주의(Command Injection).

readlines(path, sep = $/, **opts) → array

스트림에서 읽은 모든 줄의 배열을 돌려줘요. sep, limit, ''(문단), nil(전체)을 지원해요. 신뢰할 수 없는 입력 주의(Command Injection).

select(read_ios, write_ios = [], error_ios = [], timeout = nil) → array or nil

시스템 콜 select(2)을 호출해 파일 디스크립터들을 감시해요. 세 배열의 IO 객체를 감시하다 준비된 게 생기면 3-요소 배열(읽기 준비·쓰기 준비·보류 예외 배열)을 돌려줘요. timeout 안에 없으면 nil. 모든 플랫폼에서 구현된 건 아니에요. 비차단 메서드 후에 쓰는 게 최선이에요. (상세한 비차단 에뮬레이션 예시는 Kernel#select 참고)

sysopen(path, mode = 'r', perm = 0666) → integer

주어진 경로의 파일을 주어진 모드·권한으로 열고 정수 파일 디스크립터를 돌려줘요.

File.write('t.tmp', '')  # => 0
IO.sysopen('t.tmp')      # => 8
IO.sysopen('t.tmp', 'w') # => 9

try_convert(object) → new_io or nil

objectto_io로 IO 객체로 변환해 보려고 해요. 성공하면 새 IO 객체, 아니면 nil.

IO.try_convert(STDOUT)   # => #<IO:<STDOUT>>
IO.try_convert('STDOUT') # => nil

write(path, data, offset = 0, **opts) → integer

스트림을 열고 주어진 데이터를 써서 닫아요. 쓴 바이트 수를 돌려줘요. offset이 0이면 덮어쓰고, 내용 안이면 부분 덮어쓰고, 내용 밖이면 "\u0000"로 채워요. 신뢰할 수 없는 입력 주의(Command Injection).

IO.write('t.tmp', 'abc')  # => 3
IO.write('t.tmp', '012', 2) # => 3  # ab012f 가 됨
IO.write('t.tmp', 'xyz', 10) # => 3  # null로 채움

더 알아보기: 공개 인스턴스 메서드 (Public Instance Methods)

self << object → self

주어진 객체를 self에 쓰고 self를 돌려줘요 (쓰기용으로 열려 있어야 해요). 문자열이 아니면 to_s로 변환돼요.

$stdout << 'Hello' << ', ' << 'World!' << "\n"
# Hello, World!

advise(advice, offset = 0, len = 0) → nil

Posix 시스템 콜 posix_fadvise(2)을 호출해 현재 파일의 데이터에 특정 방식으로 접근할 의도를 알려요. 인자·결과는 플랫폼 의존적이에요. advice 심볼: :normal, :sequential, :random, :noreuse, :willneed, :dontneed. 모든 플랫폼에서 구현된 건 아니에요.

autoclose = bool → true or false

자동 닫기 플래그를 설정해요.

f = File.open(File::NULL)
g = IO.for_fd(f.fileno)
g.autoclose = false
g.close
f.gets # won't cause Errno::EBADF

autoclose? → true or false

기본 파일 디스크립터가 종료 시 또는 close 시 닫힐지 여부를 돌려줘요.

beep ()

콘솔 경고음. require 'io/console' 필요.

binmode → self

스트림의 데이터 모드를 바이너리로 설정해요. 바이너리에서 텍스트로는 변경할 수 없어요.

binmode? → true or false

스트림이 바이너리 모드인지 여부를 돌려줘요.

close → nil

읽기·쓰기 중 열린 쪽을 모두 닫고 nil을 돌려줘요. 쓰기용이면 버퍼를 먼저 플러시해요. IO.popen으로 열렸으면 $?를 설정해요.

close_on_exec = bool → true or false

close-on-exec 플래그를 설정해요. Ruby 2.0.0부터 모든 파일 디스크립터에 기본적으로 설정되므로 직접 설정할 필요가 없어요. 자식 프로세스에 파일 디스크립터 상속이 정말 필요하면 spawnfd=>fd 인자를 쓰세요.

close_on_exec? → true or false

스트림이 exec 시 닫힐지 여부를 돌려줘요.

close_read → nil

읽기용으로 열려 있으면 읽기용으로 닫아요. IO.popen 스트림이고 쓰기도 닫혀 있으면 $?를 설정해요.

close_write → nil

쓰기용으로 열려 있으면 쓰기용으로 닫아요. 버퍼를 먼저 플러시해요.

closed? → true or false

읽기·쓰기 모두 닫혔는지 여부를 돌려줘요.

console_mode → mode / console_mode = mode

현재 콘솔 모드를 나타내는 데이터를 돌려주거나 설정해요. require 'io/console' 필요.

cooked {|io| } / cooked!

cooked 모드로 self를 yield하거나 활성화해요. cooked! 후엔 io.cooked { ... }로 되돌려요. require 'io/console' 필요.

cursor → [row, column]

현재 커서 위치를 정수 두 요소 배열로 돌려줘요. require 'io/console' 필요.

each_byte {|byte| ... } → self

스트림의 각 바이트(0..255)로 블록을 호출하고 self를 돌려줘요. 블록이 없으면 Enumerator. 관련: each_char, each_codepoint.

f = File.new('t.rus')
a = []
f.each_byte {|b| a << b }
a # => [209, 130, 208, 181, 209, 129, 209, 130]

each_char {|c| ... } → self

스트림의 각 문자로 블록을 호출하고 self를 돌려줘요. 블록이 없으면 Enumerator.

each_codepoint {|c| ... } → self

스트림의 각 코드포인트로 블록을 호출하고 self를 돌려줘요. 블록이 없으면 Enumerator.

each_line(sep = $/, chomp: false) {|line| ... } → self · each

스트림에서 읽은 각 남은 줄로 블록을 호출하고 self를 돌려줘요. sep, limit, ''(문단), nil(전체), chomp을 지원해요. 블록이 없으면 Enumerator.

echo = flag / echo? → true or false

에코백을 활성/비활성화하거나 확인해요. require 'io/console' 필요.

eof → true or false · eof?

스트림이 끝에 있는지 여부를 돌려줘요. 읽기용이 아니면 예외. 파이프·소켓 같은 스트림이면 상대가 데이터를 보내거나 닫을 때까지 블록돼요. 이 메서드는 입력 바이트 버퍼로 데이터를 읽으므로 sysread와 함께 쓸 땐 주의하세요.

IO#expect(pattern, timeout=9999999) → Array

expect 라이브러리가 추가하는 인스턴스 메서드로 TCL expect 확장과 비슷해요. require 'expect' 필요. 주어진 패턴이 매치되거나 timeout까지 IO에서 읽어요. 읽은 버퍼와 매치 결과를 배열로 돌려줘요. 블록이 있으면 결과를 넘기고 nil을 돌려줘요.

external_encoding → encoding or nil

스트림의 인코딩을 나타내는 Encoding 객체를 돌려줘요 (쓰기 모드이고 인코딩 미지정이면 nil).

fcntl(integer_cmd, argument) → integer

Posix 시스템 콜 fcntl(2)을 호출해 파일 지향 I/O 스트림을 제어·조회하는 저수준 명령을 내려요. 인자·결과는 플랫폼 의존적. 모든 플랫폼에서 구현된 건 아니에요.

fdatasync → 0

스트림에 버퍼된 모든 데이터를 즉시 디스크에 써요 (fdatasync(2), 없으면 fsync(2)).

fileno → integer · to_i

스트림의 정수 파일 디스크립터를 돌려줘요.

$stdin.fileno  # => 0
$stdout.fileno # => 1
$stderr.fileno # => 2

flush → self

self에 버퍼된 데이터를 운영체제로 플러시해요 (OS 내부 버퍼까지는 보장하지 않아요).

fsync → 0

스트림에 버퍼된 모든 데이터를 fsync(2)으로 즉시 디스크에 써요. sync=은 내부 버퍼만 플러시하지만 fsync은 디스크 기록까지 보장해요. OS가 fsync(2)을 지원하지 않으면 예외.

getbyte → integer or nil

스트림에서 다음 바이트(0..255)를 읽어 돌려줘요. 이미 끝이면 nil. 관련: readbyte(EOFError 발생).

getc → character or nil

스트림에서 다음 1-문자 문자열을 읽어 돌려줘요. 이미 끝이면 nil. 관련: readchar.

getch(min: nil, time: nil, intr: nil) → char

raw 모드에서 문자를 읽어 돌려줘요. 매개변수는 IO#raw 참고. require 'io/console' 필요.

getpass(prompt=nil) → string

에코백 없이 줄을 읽어 돌려줘요. prompt가 nil이 아니면 출력해요. 반환 문자열에서 줄바꿈 문자가 제거돼요. require 'io/console' 필요.

require 'io/console'
IO::console.getpass("Enter password:")
# => "mypassword"

gets(sep = $/, chomp: false) → string or nil

스트림에서 줄을 읽어 돌려주고 $_에 할당해요. sep, limit, ''(문단), nil(전체), chomp 지원.

f = File.open('t.txt')
f.gets # => "First line\n"
$_     # => "First line\n"

inspect → string

self의 문자열 표현을 돌려줘요. f.inspect # => "#<File:t.txt>".

internal_encoding → encoding or nil

변환이 지정된 경우 내부 문자열 인코딩을 나타내는 Encoding 객체를, 아니면 nil을 돌려줘요.

ioctl(integer_cmd, argument) → integer

Posix 시스템 콜 ioctl(2)을 호출해 I/O 장치에 저수준 명령을 내려요. 인자·결과·효과는 플랫폼 의존적. 모든 플랫폼에서 구현된 건 아니에요.

isatty → true or false · tty?

스트림이 터미널 장치(tty)와 연결됐는지 여부를 돌려줘요.

lineno → integer / lineno = integer → integer

스트림의 현재 줄 번호를 돌려주거나 설정해요.

noecho {|io| }

에코백을 끈 채 self를 yield해요. require 'io/console' 필요.

nonblock {|io| } → object / nonblock = boolean → boolean

비차단 모드로 self를 yield하거나, nonblock =으로 O_NONBLOCK 플래그를 설정/해제해요. 대부분의 IO 메서드는 이 플래그의 영향을 받지 않아요(EAGAIN·부분 읽기/쓰기 후 시스템 콜을 재시도하므로). 예외는 IO#syswrite(재시도 안 함). 표준 I/O의 비차단 모드를 해제하는 데 유용해요:

END { STDOUT.nonblock = false }
STDOUT.write_nonblock("foo")

nonblock? → boolean

IO 객체가 비차단 모드인지 여부를 돌려줘요.

nread → int

블로킹 없이 읽을 수 있는 바이트 수를 돌려줘요. 정보가 없으면 0. require 'io/wait' 필요.

path → string or nil

IO와 연관된 경로를 돌려줘요. 없으면 nil. 파일시스템에 경로가 존재함을 보장하지 않아요.

pathconf (p1)

fpathconf()으로 경로명 구성 변수를 돌려줘요. name은 Etc 아래 PC_로 시작하는 상수. 반환값은 정수 또는 nil(무한 제한).

require 'etc'
IO.pipe {|r, w|
  p w.pathconf(Etc::PC_PIPE_BUF) #=> 4096
}

pid → integer or nil

IO#popen으로 설정된 자식 프로세스의 pid를 돌려줘요. IO#popen으로 만들지 않았으면 nil.

pos → integer · tell

현재 위치(바이트)를 돌려줘요.

pos = new_position → new_position

주어진 위치(바이트)로 이동해요.

pread(maxlen, offset) → string

IO#readpartial처럼 동작하되 주어진 오프셋에서 읽고, 스트림 위치를 건드리지 않으며, 사용자 공간 버퍼링을 우회해요. 여러 스레드·프로세스가 같은 IO를 여러 오프셋에서 읽을 수 있게 해줘요. 일부 플랫폼에서 불가.

f = File.open('t.txt')
f.pread(12, 0) # => "First line\n"
f.pread(9, 8)  # => "ne\nSecon"

print(*objects) → nil

주어진 객체들을 스트림에 써요. 각 객체를 to_s로 변환하고, 마지막이 아니면 필드 구분자 $,를, 끝에 레코드 구분자 $\(nil이 아니면)를 붙여요. 인자가 없으면 $_를 출력해요.

printf(format_string, *objects) → nil

주어진 객체들을 형식 문자열로 형식화해 스트림에 써요. Format Specifications 참고.

putc(object) → object

스트림에 문자를 써요. 숫자면 정수로 변환 후 최하위 바이트 코드의 문자를, 문자열이면 첫 문자를 써요.

$stdout.putc "A"
$stdout.putc 65
# AA

puts(*objects) → nil

주어진 객체들을 스트림에 써요. 이미 줄바꿈으로 끝나지 않으면 각 뒤에 새 줄을 써요. 인자가 없으면 새 줄을 써요. String은 그대로, 문자열·배열이 아니면 to_s, 배열은 각 요소를(중첩 가능) 씁니다.

def show(*objects)
  f = File.new('t.tmp', 'w+')
  f.puts(objects)
  f.rewind
  p f.read
  f.close
end
show('foo', 'bar', 'baz') # => "foo\nbar\nbaz\n"
show([[[0, 1], 2, 3], 4, 5])  # => "0\n1\n2\n3\n4\n5\n"

pwrite(object, offset) → integer

IO#write처럼 동작하되 주어진 오프셋에 쓰고, 스트림 위치를 건드리지 않으며, 사용자 공간 버퍼링을 우회해요. 일부 플랫폼에서 불가.

f = File.open('t.tmp', 'w+')
f.pwrite('ABCDEF', 3) # => 6
f.read # => "\u0000\u0000\u0000ABCDEF"

raw(min: nil, time: nil, intr: nil) {|io| } / raw!

raw 모드로 self를 yield하거나 활성화해요. min은 읽기 시 받을 최소 바이트(기본 1), time은 1/10초 단위 timeout(기본 0), intr이 true면 break·interrupt·quit·suspend 특수 문자 활성. raw! 후엔 io.raw { ... }로 되돌려요. require 'io/console' 필요.

read(maxlen = nil, out_string = nil) → new_string, out_string, or nil

스트림에서 바이트를 읽어요. maxlen이 nil이면 데이터 모드로 전부, 아니면 바이너리 모드로 최대 maxlen만큼 읽어요. out_string을 주면 그 내용을 교체해 돌려주고, 없으면 새 문자열을 돌려줘요. 읽은 게 없으면 nil. maxlen이 0이면 빈 문자열. C의 fread()처럼 동작해서 maxlen만큼(또는 EOF까지) read(2) 시스템 콜을 재시도해요. 비차단 모드여도 이 동작은 유지돼요. 단일 read(2) 같은 동작이 필요하면 readpartial, read_nonblock, sysread를 고려하세요.

f = File.new('t.txt')
f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n"
f.read(30) # => "First line\r\nSecond line\r\n\r\nFou"
f.read(30) # => nil

read_nonblock(maxlen [, options]) → string

기본 파일 디스크립터에 O_NONBLOCK을 설정한 후 read(2) 시스템 콜로 최대 maxlen바이트를 읽어요. read(2)이 일으키는 모든 에러(Errno::EWOULDBLOCK, Errno::EINTR 등)를 일으켜요. Errno::EWOULDBLOCK/Errno::EAGAINIO::WaitReadable로 확장되므로 이를 rescue해 재시도할 수 있어요. EOF에선 EOFError. Windows 등 일부 플랫폼에선 소켓이 아닌 IO에 비차단 모드를 지원하지 않아 Errno::EBADF가 날 수 있어요. 버퍼가 비어 있지 않으면 버퍼에서 읽어요. exception: false를 주면 IO::WaitReadable 대신 :wait_readable을 돌려주고 EOF에선 nil을 돌려줘요.

# emulates blocking read (readpartial).
begin
  result = io.read_nonblock(maxlen)
rescue IO::WaitReadable
  IO.select([io])
  retry
end

readbyte → integer

스트림에서 다음 바이트를 읽어 돌려줘요. 이미 끝이면 EOFError. 관련: getbyte.

readchar → string

스트림에서 다음 1-문자 문자열을 읽어 돌려줘요. 이미 끝이면 EOFError. 관련: getc.

readline(sep = $/, chomp: false) → string

IO#gets처럼 줄을 읽되 이미 끝이면 EOFError.

readlines(sep = $/, chomp: false) → array

스트림에서 남은 모든 줄을 읽어 배열로 돌려줘요. $_는 바꾸지 않아요.

readpartial(maxlen) → string

스트림에서 최대 maxlen바이트를 읽어 돌려줘요. 사용 가능하면 maxlen바이트, 일부만 있으면 그만큼, 없으면 빈 문자열. 데이터가 즉시 없을 때만 블록하고, 데이터가 더 오거나 EOF에 도달할 때까지 기다려요. 파이프·소켓·tty에 유용해요. sysread와 비슷하지만 버퍼가 비어 있지 않으면 버퍼에서 읽고, EWOULDBLOCK·EINTR을 일으키지 않고(재시도), 비차단 플래그에 민감하지 않아요.

f = File.new('t.txt')
f.readpartial(20) # => "First line\nSecond l"
f.readpartial(20) # => "ine\n\nFourth line\n"
f.readpartial(20) # Raises EOFError

ready? → truthy or falsy

블로킹 없이 입력이 가능하면 참 값을 돌려줘요. require 'io/wait' 필요.

reopen(other_io) → self

스트림을 다른 스트림(클래스가 달라도 됨)과 재연결해요. 기존 스트림을 새 목적지로 리다이렉트하는 데 쓰여요.

$stdin.reopen('t.txt')
$stdout.reopen('t.tmp', 'w')

rewind → 0

스트림을 처음으로 재배치하고 위치·줄 번호를 0으로 설정해요. 파이프·tty·소켓에는 사용할 수 없어요.

seek(offset, whence = IO::SEEK_SET) → 0

정수 offsetwhence 상수로 주어진 위치로 이동해요:

  • :CUR/IO::SEEK_CUR — 현재 위치 + offset
  • :END/IO::SEEK_END — 스트림 끝 + offset
  • :SET/IO:SEEK_SET — 주어진 offset으로
f = File.open('t.txt')
f.seek(20, :CUR) # => 0
f.tell           # => 20
f.seek(0, :END)  # => 0  # 스트림 끝으로
f.tell           # => 52

set_encoding(ext_enc) → self

스트림에 (외부·내부) 인코딩을 설정해요. 'ext_enc:int_enc' 형태 문자열도 지원돼요. 외부 인코딩이 binary/ASCII-8BIT면 내부 인코딩은 nil로 설정돼요.

set_encoding_by_bom → encoding or nil

스트림이 BOM으로 시작하면 BOM을 소비하고 외부 인코딩을 설정해요. 결과 인코딩을 돌려주고 없으면 nil. 스트림이 binmode가 아니거나 인코딩이 이미 설정돼 있으면 예외.

stat → stat

ios에 대한 상태 정보를 File::Stat 타입 객체로 돌려줘요.

f = File.new("testfile")
s = f.stat
"%o" % s.mode   #=> "100644"
s.blksize       #=> 4096

sync → true or false

스트림의 현재 sync 모드를 돌려줘요. true면 모든 출력이 즉시 OS로 플러시되고 Ruby 내부에서 버퍼링되지 않아요. fsync도 참고.

sync = boolean → boolean

스트림의 sync 모드를 설정해요. true면 즉시 플러시, false면 내부 버퍼링 가능.

sysread(maxlen) → string

IO#readpartial처럼 동작하되 저수준 시스템 함수를 사용해요. 다른 스트림 읽기 메서드와 함께 쓰지 마세요.

sysseek(offset, whence = IO::SEEK_SET) → integer

IO#seek처럼 동작하되 저수준 함수를 쓰고 새 위치를 돌려줘요.

syswrite(object) → integer

주어진 객체를 self에 쓰고 쓴 바이트 수를 돌려줘요. 문자열이 아니면 to_s로 변환. 다른 스트림 쓰기 메서드와 함께 쓰지 마세요.

tell → integer

현재 위치(바이트)를 돌려줘요.

timeout → duration or nil / timeout = duration → duration

내부 timeout 지속시간을 돌려주거나 설정해요. 설정된 시간보다 오래 걸리면 IO::TimeoutError. gets, puts, read, write, wait_readable, wait_writableSocket#accept·Socket#connect 같은 블로킹 소켓 연산에 영향을 줘요. File#open·IO#close는 영향받지 않아요. 느린 I/O(slowloris 공격 등)에서 앱이 멈추는 걸 막는 최후의 수단이에요.

to_io → self

self를 돌려줘요.

ungetbyte(integer) → nil

주어진 데이터를 스트림 버퍼에 밀어 넣어("unshift") 다음에 읽히게 해요. 정수면 최하위 바이트만, 문자열이면 모든 바이트를 사용해요. 무버퍼 읽기(sysread)엔 효과가 없고, rewind는 밀어 넣은 데이터를 버려요.

ungetc(integer) → nil

주어진 데이터를 스트림 버퍼에 밀어 넣어 다음에 읽히게 해요. 정수는 문자로 해석, 문자열은 모든 문자를 사용해요. 무버퍼 읽기엔 효과가 없고 rewind는 버려요.

wait(events, timeout) → event mask, false or nil

IO가 지정된 이벤트에 준비될 때까지 기다리고 준비된 이벤트의 부분집합을 돌려줘요. eventsIO::READABLE, IO::WRITABLE, IO::PRIORITY의 비트 마스크. require 'io/wait' 필요.

wait_priority → truthy or falsy

IO가 priority가 될 때까지 기다려요. Priority 데이터는 Socket::MSG_OOB 플래그로 보내져요. require 'io/wait' 필요.

wait_readable → truthy or falsy

IO가 읽을 수 있을 때까지 기다려요. 버퍼된 데이터가 있으면 즉시 참 값을 돌려줘요. require 'io/wait' 필요.

wait_writable → truthy or falsy

IO가 쓸 수 있을 때까지 기다려요. require 'io/wait' 필요.

winsize → [rows, columns] / winsize = [rows, columns]

콘솔 크기를 돌려주거나 설정을 시도해요. require 'io/console' 필요.

write(*objects) → integer

주어진 각 객체를 self에 쓰고 총 쓴 바이트 수를 돌려줘요. 문자열이 아닌 객체는 to_s로 변환돼요.

$stdout.write('Hello', ', ', 'World!', "\n") # => 14

write_nonblock(string) → integer

기본 파일 디스크립터에 O_NONBLOCK을 설정한 후 write(2) 시스템 콜로 문자열을 써요. 쓴 바이트 수를 돌려줘요. write(2)이 일으키는 모든 에러를 일으키고 부분 쓰기가 있을 수 있어요. Errno::EWOULDBLOCK/Errno::EAGAINIO::WaitWritable로 확장돼요. 쓰기 버퍼가 비어 있지 않으면 먼저 플러시해요. exception: false를 주면 IO::WaitWritable 대신 :wait_writable을 돌려줘요.

begin
  result = io.write_nonblock(string)
rescue IO::WaitWritable, Errno::EINTR
  IO.select(nil, [io])
  retry
end