Ruby 1.9.2 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > ARGFオブジェクト

object ARGF

クラスの継承リスト: ARGF
extend: Enumerable

Abstract

スクリプトに指定した引数 (Kernel::ARGV を参照) をファイル名とみなして、 それらのファイルを連結した 1 つの仮想ファイルを表すオブジェクトです。 ARGV が空なら標準入力を対象とします。 ARGV を変更すればこのオブジェクトの動作に影響します。

while line = ARGF.gets
  ....
end

は、

while argv = ARGV.shift
  File.open(argv) {|file|
    while line = file.gets
      ....
    end
  }
end

のように動作します。

ARGF を処理するごとに ARGV の要素は一つずつ取り除かれます。 最後まで ARGF を読み込んだ後、再度 ARGF から内容を読むと (ARGV が空なので)標準入力からの読み込みとなります。

ARGV.replace %w(/tmp/foo /tmp/bar)
ARGF.each {|line|
    # 処理中の ARGV の内容を表示
    p [ARGF.filename, ARGV]
    ARGF.skip
}
    # => ["/tmp/foo", ["/tmp/bar"]]
    #    ["/tmp/bar", []]
# 最後まで読んだ後 (ARGV が空) の動作
p ARGF.gets      # => nil
p ARGF.filename  # => "-"

Kernel.#gets など一部の組み込み関数は ARGF.gets などこのオブジェクトをレシーバとしたメソッドの省略形です。

特異メソッド

binmode -> self

IO#binmodeを参照

require 'md5'

ARGV.replace(
  Dir.glob("*").select{|name| FileTest.file?(name)}
)
files = ARGV.dup
bm = ARGF.binmode.readlines(nil)
bm.each_with_index {|bl, i|
  md5 = MD5.new(bl).hexdigest
  printf("%s\t%s\n", md5, files[i])
}

#例
#=> fe413bf114e16b0cd596d869743e9d35        ruby-1.8.5-p35.tar.gz
#=> 70ad729e965c9625d2dfb7fa0145b423        sample.yaml
#=> d91e81b81673279e908a1c08e8582487        test.rb
#=> 158c4a0a097379a08bd88abfca6a51c5        test.rb~
#...

[SEE_ALSO] IO#binmode

bytes -> Enumerable::Enumerator

自身を 1 バイトずつ整数としてイテレートするような Enumerable::Enumerator オブジェクトを生成して返します。

ARGF.bytes.to_a        #=> [104, 101, 108, 108, 111]
each_char {|c| ... } -> self
chars {|c| ... } -> self
each_char -> Enumerable::Enumerator
chars -> Enumerable::Enumerator

レシーバに含まれる文字を一文字つつブロックに渡して評価します。

レシーバは読み込み可能でなければなりません。

また、マルチバイト文字列を使用する場合は $KCODE を適切に設定してください。

[SEE_ALSO] IO#each_char, IO#chars

close -> self

処理対象のファイルをクローズします。開くファイルが残っている場合は次のファイルをオープンします

# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").reject{|name| FileTest.file?(name) == false}
)
ARGF.each {|line|
  p [ line.chomp, ARGF.filename ]
  ARGF.close
  if ARGF.closed?
    p "ARGF is closed."
  else
    p "ARGF is not closed"
  end
}
if ARGF.closed?
  p "ARGF had been closed."
else
  p "ARGF is not closed"
end

#例
#=> ["cat:", "sample.yaml"]
#=> "ARGF is not closed"
#=> ["", "test.rb"]
#=> "ARGF is not closed"
#=> ["--- !ruby/object:Dog ", "ugo.yaml"]
#=> "ARGF is closed."
#=> "ARGF had been closed."
closed? -> bool

ARGFがcloseされていればtrueを返します。

# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").reject{|name| FileTest.file?(name) == false}
)
ARGF.each {|line|
  p [ line.chomp, ARGF.filename ]
  ARGF.close
  if ARGF.closed?
    p "ARGF is closed."
  else
    p "ARGF is not closed"
  end
}
if ARGF.closed?
  p "ARGF had been closed."
else
  p "ARGF is not closed"
end

#例
#=> ["cat:", "sample.yaml"]
#=> "ARGF is not closed"
#=> ["", "test.rb"]
#=> "ARGF is not closed"
#=> ["--- !ruby/object:Dog ", "ugo.yaml"]
#=> "ARGF is closed."
#=> "ARGF had been closed."

[SEE_ALSO] IO#closed?

each(rs = $/) {|line| ... } -> self
each_line(rs = $/) {|line| ... } -> self
each(rs = $/) -> Enumerable::Enumerator
each_line(rs = $/) -> Enumerable::Enumerator

ARGFの現在位置から一行ずつ文字列として読み込みます。

[PARAM] rs:
区切り文字を指定する
ARGV.replace(
  Dir.glob("*").reject{|name| FileTest.file?(name) == false}
)
ARGF.each_line {|line|
  line.chomp!
  printf("'%s' in %s\n", line, ARGF.filename)
}
#例
#=> '--- !ruby/object:Dog ' in ugo.yaml
#=> 'name: pochi' in ugo.yaml
#=> '--- ' in ugo.yaml
#=> ':age: 17' in ugo.yaml
#=> ':color: white' in ugo.yaml
#=> '--- ' in ugo.yaml
#=> '- Chiba' in ugo.yaml
#=> '- Saitama' in ugo.yaml

[SEE_ALSO] IO#each, IO#each_line,

each_byte {|char| ...} -> self
each_byte -> Enumerable::Enumerator

ARGF の現在位置から 1 バイトずつ読み込み、それを整数として与え、ブロックを実行します。

# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").reject{|name| FileTest.file?(name) == false}
)
ARGF.each_byte {|b|
  printf("%4d <-> %4s\n", b, b.chr)
}
#例
#=>  45 <->    -
#=>  32 <->
#=>  83 <->    S
#=>  97 <->    a
#=> 105 <->    i
#=> 116 <->    t
#=>  97 <->    a
#=> 109 <->    m
#=>  97 <->    a
#=>  10 <->
#...

[SEE_ALSO] IO#each_byte

eof -> bool
eof? -> bool

現在開いているファイルがeofに達したらtrueを返します。そうでない場合はfalseを返します。

[EXCEPTION] IOError:
ファイルがopenされていない場合
# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").reject{|name| FileTest.file?(name) == false}
)
n = 0
ARGF.each_line {|line|
  n += 1
  if ARGF.eof
    printf("eof. %s has %d(%d) line\n", ARGF.filename, n, ARGF.lineno)
    n = 0
  end
}
begin
  if ARGF.eof?
    printf("%s is eof\n", ARGF.filename)
  end
rescue IOError
  print "IOError !!\n"
end

#=> 例
#=> eof. sample.yaml has 13(13) line
#=> eof. test.rb has 159(172) line
#=> eof. test.rb~ has 159(331) line
#=> eof. third.txt has 1(332) line
#=> eof. ugo.yaml has 8(340) line
#=> IOError !!

[SEE_ALSO] IO#eof, IO#eof?

file -> IO

処理対象の File オブジェクト(または IO オブジェクト)を 返します。

ARGV.replace(
  Dir.glob("*").select{|name| FileTest.file?(name)}
)

until ARGF.closed?
  printf("最終更新時刻 %s (%s)\n", ARGF.file.stat.mtime, ARGF.filename)
  ARGF.skip
end
#例
#=> 最終更新時刻 Thu May 03 14:05:53 +0900 2007 (sample.yaml)
#=> 最終更新時刻 Sun Aug 26 11:28:09 +0900 2007 (test.rb)
#=> 最終更新時刻 Sun Aug 26 11:27:58 +0900 2007 (test.rb~)
#=> 最終更新時刻 Sun Jun 24 13:08:12 +0900 2007 (third.txt)
#=> 最終更新時刻 Sun May 20 21:34:25 +0900 2007 (ugo.yaml)

$stdinがIOオブジェクトでない場合は$stdinを返します。

class MyIO
  def to_io
    DATA
  end
end

$stdin = MyIO.new
ARGV.push("-");

p ARGF.file                #=> #<MyIO:0x293e840>
p ARGF.file.to_io.readline #=> "MyIO Test\n"

__END__
MyIO Test
です。

[SEE_ALSO] ARGF.to_io

filename -> String
path -> String

処理対象のファイル名を返します。 標準入力に対しては - を返します。 組み込み変数 $FILENAME と同じです。

# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").reject{|name| FileTest.file?(name) == false}
)
ARGF.each {|line|
  p [ARGF.filename, ARGF.path, ARGV]
  ARGF.skip
}
#例
#=> ["test.rb", "test.rb", ["test.rb~", "third.txt", "ugo.yaml"]]
#=> ["test.rb~", "test.rb~", ["third.txt", "ugo.yaml"]]
#...
fileno -> Integer
to_i -> Integer

現在オープンしているファイルのファイル記述子を表す整数を返します。

# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").reject{|name| FileTest.file?(name) == false}
)
ARGF.each_line {|line|
  p [ ARGF.to_i, ARGF.filename ]
  ARGF.skip
}
begin
  p [ ARGF.to_i, ARGF.filename ]
rescue ArgumentError
  print "ArgumentError\n"
end
#例
#=> [3, "sample.yaml"]
#=> [3, "test.rb"]
#=> [3, "test.rb~"]
#=> [3, "third.txt"]
#=> [3, "ugo.yaml"]
#=> ArgumentError
[EXCEPTION] ArgumentError:
getbyte -> Integer | nil

自身から 1 バイトを読み込み整数として返します。 既に EOF に達していれば nil を返します。

ARGF.getbyte   #=> 84
ARGF.getbyte   #=> 104
getc -> Integer | nil

ARGFから 1 文字読み込んで、その文字に対応する Fixnum を返します。EOF に到達した時には nil を返します。

# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").reject{|name| FileTest.file?(name) == false}
)

while c = ARGF.getc
  printf("%d,%c.\n", c, c)
end
#例
#=> 45,-.
#=> 32, .
#=> 67,C.
#=> 104,h.
#=> 105,i.
#=> 98,b.
#=> 97,a.
#=> 10,
#=> .
#...
gets -> String | nil

ARGFの現在位置から一行ずつ文字列として読み込みます。EOF に到達した時には nil を返します。

# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").reject{|name| FileTest.file?(name) == false}
)

while line = gets
  line.chomp!
  printf("%s\n", line)
end

[SEE_ALSO] Kernel.#gets

lineno -> Integer

全引数ファイルを一つのファイルとみなしたときの現在の行番号を返します。 個々の引数ファイル毎の行番号を得るには ARGF.file.lineno とします。

# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").reject{|name| FileTest.file?(name) == false}
)
ARGF.each {|line|
  if ARGF.lineno < 10
    ARGF.lineno = 10
  end
  p [ ARGF.lineno, line]
}
#例
#=> [10, "cat:\n"]
#=> [11, " - name: taro\n"]
#=> [12, "   age: 7\n"]
#...
lineno=(number) -> nil

全引数ファイルを一つのファイルとみなしたときの現在の行番号をnumberに書き換えます

[PARAM] number:
更新後の行番号を指定する
ARGV.replace(
  Dir.glob("*").reject{|name| FileTest.file?(name) == false}
)

ARGF.each {|line|
  if ARGF.lineno == 4
    ARGF.lineno = 5
  end
  p [ARGF.lineno, line]
}
#=> 例
#=> [1, "cat:\n"]
#=> [2, " - name: taro\n"]
#=> [3, "   age: 7\n"]
#=> [5, " - name: jiro\n"]
#=> [6, "   age: 23\n"]
# ...
lines(rs = $/) -> Enumerable::Enumerator

自身を 1 行ずつイテレートするような Enumerable::Enumerator オブジェクトを生成して返します。

テキスト読み込みメソッドとして動作します。

[PARAM] rs:
行の区切りを文字列で指定します。rs に nil を指定すると行区切りなしとみなします。 空文字列 "" を指定すると連続する改行を行の区切りとみなします(パラグラフモード)。
ARGF.lines.to_a   #=> ["foo\n", "bar\n"]

[SEE_ALSO] $/

pos -> Integer
tell -> Integer

ARGFが現在開いているファイルのファイルポインタの現在の位置を整数で返します。

ARGV.replace(
  Dir.glob("*").reject{|name| FileTest.file?(name) == false}
)

while c = ARGF.getc
  printf("%d '%c' %s\n", ARGF.pos, c, ARGF.filename)
  if ARGF.pos == 3
    ARGF.skip
  end
end

# 例
#=> 1 'c' sample.yaml
#=> 2 'a' sample.yaml
#=> 3 't' sample.yaml
#=> 1 '#' test.rb
#=> 2 '!' test.rb
#=> 3 '/' test.rb
#=> 1 'd' third.txt
#=> 2 'r' third.txt
#=> 3 'y' third.txt
#...

[SEE_ALSO] IO#pos, IO#tell

pos=(n)

ARGFが開いているファイルのファイルポインタを指定位置に移動します

[PARAM] n:
先頭からのオフセットを整数で指定します。
# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").select{|name| FileTest.file?(name)}
)
print ARGF.readline
#例
#=> #!/usr/bin/env ruby
ARGF.pos = 2
print ARGF.readline
#=> /usr/bin/env ruby
ARGF.pos = 4
print ARGF.readline
#=> sr/bin/env ruby

[SEE_ALSO] IO#pos=

read(length = nil, str = nil) -> String

ARGVに指定されたファイルを先頭のファイルからlengthバイト読み込み、 その文字列をstrに出力します。読み込んだ文字列を返します。

[PARAM] length:
読み込むバイト数を指定します nilの場合はARGVのすべてのファイルを読み込みます。
[PARAM] str:
出力先の文字列
# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").select{|name| FileTest.file?(name)}
)

str = "efefefe"
ARGF.read(100, str)
p str.size #=> 100
p str
# 例
#=> "cat:\n - name: taro\n   age: 7\n - name: jiro\n   age: 23\n---\ndog:\n shiba:\n- name: goro\n    age: 3\n  -"

[SEE_ALSO] IO#read

readbyte -> Integer

自身から 1 バイトを読み込み整数として返します。 既に EOF に達していれば EOFError が発生します。

[EXCEPTION] EOFError:
既に EOF に達している場合に発生します。
readchar -> Integer

ARGFから 1 文字読み込んで、その文字に対応する Fixnum を返します。EOF に到達した時には EOFErrorを発生します。

[EXCEPTION] EOFError:
EOFに達した時発生する
# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").select{|name| FileTest.file?(name)}
)

begin
  c = ARGF.readchar
  printf("%4c is %4d\n", c, c)
rescue EOFError
  p $!
  break
end while true

# 例
#...
#=>    t is  116
#=>    a is   97
#=>    m is  109
#=>    a is   97
#=>
#=>  is   10
#<EOFError: end of file reached>

[SEE_ALSO] ARGF.getc

readline -> String

ARGFの現在位置から一行ずつ文字列として読み込みます。EOF に到達した時にはEOFErrorを発生します。

[EXCEPTION] EOFError:
EOFに達したら発生する
# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").select{|name| FileTest.file?(name)}
)

begin
  line = ARGF.readline
  p line
rescue EOFError
  p $!
  break
end while true

#例
#...
#=> "- Saitama\n"
#=> <EOFError: end of file reached>

[SEE_ALSO] Kernel.#readline ARGF.gets

readlines(rs = $/) -> [String]
to_a(rs = $/) -> [String]

ARGFの各行を配列に読み込んで返します。rsがnilの場合は要素に各ファイルをすべて読み込んだ配列を返します。

[PARAM] rs:
行区切り文字
# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").select{|name| FileTest.file?(name)}
)
aall = ARGF.readlines
p aall[0, 3]
# 例
#=> ["cat:\n", " - name: taro\n", "   age: 7\n"]
p ARGF.closed? #=> true

ARGV.replace(
  Dir.glob("*").select{|name| FileTest.file?(name)}
)

vsize = ARGV.size
aall = ARGF.readlines(nil)
p ARGF.closed? #=> true
p vsize == aall.size #=> true

[SEE_ALSO] $/ IO#readlines

readpartial(length, str = nil)

IO#readpartialを参照

[SEE_ALSO] IO#readpartial

rewind -> 0

ARGFが現在開いているファイルのファイルポインタを先頭に戻します。

# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").select{|name| FileTest.file?(name)}
)

#各ファイルの先頭から3行を2回表示する
until ARGF.closed?
  1.upto(2){|i|
    printf("filename:%s at %d\n", ARGF.filename, i)
    1.upto(3){
      line = ARGF.readline
      p line
      break if ARGF.eof?
    }
    ARGF.rewind
  }
  ARGF.skip
end
seek(offset, whence = IO::SEEK_SET) -> 0

ARGFが現在開いているファイルのファイルポインタを whence の位置から offset だけ移動させます。 offset 位置への移動が成功すれば 0 を返します。

[PARAM] offset:
ファイルポインタを移動させるオフセットを整数で指定します。
[PARAM] whence:
IO#seekを参照
# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").select{|name| FileTest.file?(name)}
)

until ARGF.closed?
  begin
    ARGF.seek(-13, IO::SEEK_END)
    printf "(%s):%s", ARGF.filename, ARGF.readline
  rescue Errno::EINVAL
    printf "Error %s (%s)\n", ARGF.filename, $!.to_s
  end
  ARGF.skip
end
#例
#=> (sample.yaml):d of sample
#=> (test.rb):.skip
#=> (test.rb~):.skip
#=> Error third.txt (Invalid argument - third.txt)
#=> (ugo.yaml):

[SEE_ALSO] IO#seek

skip -> self

処理対象のファイルをクローズします。 次回の読み込みは次の引数が処理対象になります。 self を返します。

# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").reject{|name| FileTest.file?(name) == false}
)
while line = ARGF.gets
  p [ARGF.filename, ARGV, ARGF.skip]
end
#例
#=> ["sample.yaml", ["test.rb", "test.rb~", "third.txt", "ugo.yaml"], ARGF]
#=> ["test.rb", ["test.rb~", "third.txt", "ugo.yaml"], ARGF]
#...
to_io -> IO

ARGFが現在開いているファイルのFile、またはIOオブジェクトを返します

# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").select{|name| FileTest.file?(name)}
)

until ARGF.closed?
  printf("最終更新時刻 %s (%s)\n", ARGF.to_io.stat.mtime, ARGF.filename)
  ARGF.skip
end
#例
#=> 最終更新時刻 Thu May 03 14:05:53 +0900 2007 (sample.yaml)
#=> 最終更新時刻 Sat Aug 18 16:31:42 +0900 2007 (test.rb)
#=> 最終更新時刻 Sat Aug 18 16:31:30 +0900 2007 (test.rb~)
#=> 最終更新時刻 Sun Jun 24 13:08:12 +0900 2007 (third.txt)
#=> 最終更新時刻 Sun May 20 21:34:25 +0900 2007 (ugo.yaml)
#...

$stdinがIOオブジェクトでない場合は$stdin.to_ioを呼び出します。

class MyIO
  def to_io
    DATA
  end
end

$stdin = MyIO.new
ARGV.push("-")

myio = ARGF.to_io
p myio.readline #=> "MyIO Test\n"
p ARGF.file     #=> #<MyIO:0x293ea34>

__END__
MyIO Test
です。

[SEE_ALSO] ARGF.file

to_s -> String

常に文字列 "ARGF" を返します。

# カレントディレクトリから適当にファイルを選ぶ
ARGV.replace(
  Dir.glob("*").reject{|name| FileTest.file?(name) == false}
)
while line = ARGF.gets
  p [ARGF.filename, ARGF.to_s, ARGV]
  ARGF.skip
end

#例
#=> ["test.rb", "ARGF", ["test.rb~", "third.txt", "ugo.yaml"]]
#=> ["test.rb~", "ARGF", ["third.txt", "ugo.yaml"]]
#...

Methods

Classes