類別 ARGF
ARGF
是專門用於處理命令列引數或透過 STDIN 傳入檔案的指令碼的串流。
傳遞給指令碼的引數會儲存在 ARGV
陣列
中,每個元素一個引數。 ARGF
假設從 ARGV
中已移除任何不是檔案名稱的引數。例如
$ ruby argf.rb --verbose file1 file2 ARGV #=> ["--verbose", "file1", "file2"] option = ARGV.shift #=> "--verbose" ARGV #=> ["file1", "file2"]
現在,您可以使用 ARGF
來處理這些命名檔案的串接。例如, ARGF.read
會傳回 file1 的內容,後接 file2 的內容。
在 ARGV
中的檔案讀取完畢後, ARGF
會從 陣列
中將其移除。因此,在所有檔案都讀取完畢後, ARGV
將會是空的。
您可以自行操作 ARGV
來控制 ARGF
的運作方式。如果您從 ARGV
中移除檔案, ARGF
會忽略它;如果您將檔案新增到 ARGV
,則會將其視為在命令列中命名。例如
ARGV.replace ["file1"] ARGF.readlines # Returns the contents of file1 as an Array ARGV #=> [] ARGV.replace ["file2", "file3"] ARGF.read # Returns the contents of file2 and file3
如果 ARGV
為空, ARGF
會像包含 "-"
一樣運作,這會讓 ARGF
從 STDIN 讀取,也就是傳遞給或輸入到指令碼的資料。例如
$ echo "glark" | ruby -e 'p ARGF.read' "glark\n" $ echo Glark > file1 $ echo "glark" | ruby -e 'p ARGF.read' -- - file1 "glark\nGlark\n"
公開實例方法
傳回 ARGV
陣列,其中包含傳遞給指令碼的引數,每個元素一個引數。
例如
$ ruby argf.rb -v glark.txt ARGF.argv #=> ["-v", "glark.txt"]
static VALUE argf_argv(VALUE argf) { return ARGF.argv; }
如果 ARGF
以二進位模式讀取,則傳回 true;否則傳回 false。若要啟用二進位模式,請使用 ARGF.binmode
。
例如
ARGF.binmode? #=> false ARGF.binmode ARGF.binmode? #=> true
static VALUE argf_binmode_p(VALUE argf) { return RBOOL(ARGF.binmode); }
關閉目前檔案並跳到 ARGV 中的下一檔案。如果沒有更多檔案要開啟,則只關閉目前檔案。STDIN 仍會保持開啟。
例如
$ ruby argf.rb foo bar ARGF.filename #=> "foo" ARGF.close ARGF.filename #=> "bar" ARGF.close
static VALUE argf_close_m(VALUE argf) { next_argv(); argf_close(argf); if (ARGF.next_p != -1) { ARGF.next_p = 1; } ARGF.lineno = 0; return argf; }
如果目前檔案已關閉,則傳回 true;否則傳回 false。使用 ARGF.close
來實際關閉目前檔案。
static VALUE argf_closed(VALUE argf) { next_argv(); ARGF_FORWARD(0, 0); return rb_io_closed_p(ARGF.current_file); }
傳回一個列舉器,對 ARGV
中每個檔案的每一行(以 sep 分隔,預設為平台的換行字元)進行反覆運算。如果提供區塊,則會將每一行依序傳遞給區塊,否則會傳回一個列舉器。選用的 limit 參數是一個 Integer
,用於指定每一行的最大長度;較長的列會根據此限制進行分割。
此方法允許您將命令列上提供的檔案視為一個單一檔案,由每個命名檔案的串接組成。在第一個檔案的最後一行傳回後,會傳回第二個檔案的第一行。 ARGF.filename
和 ARGF.lineno
方法可用於分別判斷目前行的檔案名稱和整個輸入的列號。
例如,下列程式碼會印出每個命名檔案的每一行,並加上其列號,每個檔案只顯示一次檔案名稱
ARGF.each_line do |line| puts ARGF.filename if ARGF.file.lineno == 1 puts "#{ARGF.file.lineno}: #{line}" end
而下列程式碼只會先印出第一個檔案的名稱,然後印出所有命名檔案的內容,並計算列號。
ARGF.each_line do |line| puts ARGF.filename if ARGF.lineno == 1 puts "#{ARGF.lineno}: #{line}" end
static VALUE argf_each_line(int argc, VALUE *argv, VALUE argf) { RETURN_ENUMERATOR(argf, argc, argv); FOREACH_ARGF() { argf_block_call_line(rb_intern("each_line"), argc, argv, argf); } return argf; }
逐一反覆處理 ARGV
中每個檔案的每個位元組。位元組以 0..255 範圍內的 Integer
型態傳回。
這個方法讓您能將命令列上提供的檔案視為由每個指定檔案串接而成的單一檔案。在傳回第一個檔案的最後一個位元組後,會傳回第二個檔案的第一個位元組。可以使用 ARGF.filename
方法來判斷目前位元組的檔案名稱。
如果沒有提供區塊,則會傳回一個列舉器。
例如
ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
static VALUE argf_each_byte(VALUE argf) { RETURN_ENUMERATOR(argf, 0, 0); FOREACH_ARGF() { argf_block_call(rb_intern("each_byte"), 0, 0, argf); } return argf; }
逐一反覆處理 ARGF
中每個檔案的每個字元。
這個方法讓您能將命令列上提供的檔案視為由每個指定檔案串接而成的單一檔案。在傳回第一個檔案的最後一個字元後,會傳回第二個檔案的第一個字元。可以使用 ARGF.filename
方法來判斷目前字元出現的檔案名稱。
如果沒有提供區塊,則會傳回一個列舉器。
static VALUE argf_each_char(VALUE argf) { RETURN_ENUMERATOR(argf, 0, 0); FOREACH_ARGF() { argf_block_call(rb_intern("each_char"), 0, 0, argf); } return argf; }
逐一反覆處理 ARGF
中每個檔案的每個碼點。
這個方法讓您能將命令列上提供的檔案視為由每個指定檔案串接而成的單一檔案。在傳回第一個檔案的最後一個碼點後,會傳回第二個檔案的第一個碼點。可以使用 ARGF.filename
方法來判斷目前碼點出現的檔案名稱。
如果沒有提供區塊,則會傳回一個列舉器。
static VALUE argf_each_codepoint(VALUE argf) { RETURN_ENUMERATOR(argf, 0, 0); FOREACH_ARGF() { argf_block_call(rb_intern("each_codepoint"), 0, 0, argf); } return argf; }
傳回一個列舉器,對 ARGV
中每個檔案的每一行(以 sep 分隔,預設為平台的換行字元)進行反覆運算。如果提供區塊,則會將每一行依序傳遞給區塊,否則會傳回一個列舉器。選用的 limit 參數是一個 Integer
,用於指定每一行的最大長度;較長的列會根據此限制進行分割。
此方法允許您將命令列上提供的檔案視為一個單一檔案,由每個命名檔案的串接組成。在第一個檔案的最後一行傳回後,會傳回第二個檔案的第一行。 ARGF.filename
和 ARGF.lineno
方法可用於分別判斷目前行的檔案名稱和整個輸入的列號。
例如,下列程式碼會印出每個命名檔案的每一行,並加上其列號,每個檔案只顯示一次檔案名稱
ARGF.each_line do |line| puts ARGF.filename if ARGF.file.lineno == 1 puts "#{ARGF.file.lineno}: #{line}" end
而下列程式碼只會先印出第一個檔案的名稱,然後印出所有命名檔案的內容,並計算列號。
ARGF.each_line do |line| puts ARGF.filename if ARGF.lineno == 1 puts "#{ARGF.lineno}: #{line}" end
如果 ARGF
中的目前檔案已達檔案結尾(亦即沒有資料可讀取),則傳回 true。串流必須開啟為讀取模式,否則會引發 IOError
。
$ echo "eof" | ruby argf.rb ARGF.eof? #=> false 3.times { ARGF.readchar } ARGF.eof? #=> false ARGF.readchar #=> "\n" ARGF.eof? #=> true
static VALUE argf_eof(VALUE argf) { next_argv(); if (RTEST(ARGF.current_file)) { if (ARGF.init_p == 0) return Qtrue; next_argv(); ARGF_FORWARD(0, 0); if (rb_io_eof(ARGF.current_file)) { return Qtrue; } } return Qfalse; }
如果 ARGF
中的目前檔案已達檔案結尾(亦即沒有資料可讀取),則傳回 true。串流必須開啟為讀取模式,否則會引發 IOError
。
$ echo "eof" | ruby argf.rb ARGF.eof? #=> false 3.times { ARGF.readchar } ARGF.eof? #=> false ARGF.readchar #=> "\n" ARGF.eof? #=> true
以 Encoding
物件傳回從 ARGF
讀取的檔案的外部編碼。外部編碼是儲存在檔案中的文字編碼。與 ARGF.internal_encoding
形成對比,後者是在 Ruby 中表示此文字所使用的編碼。
若要設定外部編碼,請使用 ARGF.set_encoding
。
例如
ARGF.external_encoding #=> #<Encoding:UTF-8>
static VALUE argf_external_encoding(VALUE argf) { return argf_encoding(argf, rb_io_external_encoding); }
傳回目前的檔案名稱。當目前的檔案為 STDIN 時,會傳回 “-”。
例如
$ echo "foo" > foo $ echo "bar" > bar $ echo "glark" > glark $ ruby argf.rb foo bar glark ARGF.filename #=> "foo" ARGF.read(5) #=> "foo\nb" ARGF.filename #=> "bar" ARGF.skip ARGF.filename #=> "glark"
static VALUE argf_filename(VALUE argf) { next_argv(); return ARGF.filename; }
傳回代表目前檔案數值檔案描述符的整數。如果沒有目前的檔案,會引發 ArgumentError
。
ARGF.fileno #=> 3
static VALUE argf_fileno(VALUE argf) { if (!next_argv()) { rb_raise(rb_eArgError, "no stream"); } ARGF_FORWARD(0, 0); return rb_io_fileno(ARGF.current_file); }
從 ARGF
取得下一個 8 位元組 (0..255)。如果在串流的結尾呼叫,會傳回 nil
。
例如
$ echo "foo" > file $ ruby argf.rb file ARGF.getbyte #=> 102 ARGF.getbyte #=> 111 ARGF.getbyte #=> 111 ARGF.getbyte #=> 10 ARGF.getbyte #=> nil
static VALUE argf_getbyte(VALUE argf) { VALUE ch; retry: if (!next_argv()) return Qnil; if (!RB_TYPE_P(ARGF.current_file, T_FILE)) { ch = forward_current(rb_intern("getbyte"), 0, 0); } else { ch = rb_io_getbyte(ARGF.current_file); } if (NIL_P(ch) && ARGF.next_p != -1) { argf_close(argf); ARGF.next_p = 1; goto retry; } return ch; }
從 ARGF
讀取下一個字元,並以 String
傳回。在串流的結尾傳回 nil
。
ARGF
將命令列中指定的名稱檔案視為一個檔案,其內容是串接而成的。傳回第一個檔案的最後一個字元後,會傳回第二個檔案的第一個字元,依此類推。
例如
$ echo "foo" > file $ ruby argf.rb file ARGF.getc #=> "f" ARGF.getc #=> "o" ARGF.getc #=> "o" ARGF.getc #=> "\n" ARGF.getc #=> nil ARGF.getc #=> nil
static VALUE argf_getc(VALUE argf) { VALUE ch; retry: if (!next_argv()) return Qnil; if (ARGF_GENERIC_INPUT_P()) { ch = forward_current(rb_intern("getc"), 0, 0); } else { ch = rb_io_getc(ARGF.current_file); } if (NIL_P(ch) && ARGF.next_p != -1) { argf_close(argf); ARGF.next_p = 1; goto retry; } return ch; }
傳回 ARGF
中目前檔案的下一行。
預設情況下,假設行是由 $/
分隔;若要使用不同的字元作為分隔符號,請提供 String
作為 sep 參數。
選用的 limit 參數指定要傳回每一行的字元數。預設情況下,會傳回所有字元。
有關 getline_args 的詳細資訊,請參閱 IO.readlines
。
static VALUE argf_gets(int argc, VALUE *argv, VALUE argf) { VALUE line; line = argf_getline(argc, argv, argf); rb_lastline_set(line); return line; }
傳回在原處編輯模式下,附加到已修改檔案備份副本名稱的檔案副檔名。可以使用 ARGF.inplace_mode=
或將 -i
開關傳遞給 Ruby 二進位檔來設定此值。
static VALUE argf_inplace_mode_get(VALUE argf) { if (!ARGF.inplace) return Qnil; if (NIL_P(ARGF.inplace)) return rb_str_new(0, 0); return rb_str_dup(ARGF.inplace); }
將原處編輯模式的檔案名稱副檔名設定為指定的 String
。每個正在編輯的檔案的備份副本都會將此值附加到其檔案名稱。
例如
$ ruby argf.rb file.txt ARGF.inplace_mode = '.bak' ARGF.each_line do |line| print line.sub("foo","bar") end
首先,file.txt.bak 會建立為 file.txt 的備份。然後,file.txt 的每一行都會將第一次出現的「foo」替換成「bar」。
static VALUE argf_inplace_mode_set(VALUE argf, VALUE val) { if (!RTEST(val)) { ARGF.inplace = Qfalse; } else if (StringValueCStr(val), !RSTRING_LEN(val)) { ARGF.inplace = Qnil; } else { ARGF.inplace = rb_str_new_frozen(val); } return argf; }
傳回從 ARGF
讀取的字串的內部編碼,為 Encoding
物件。
如果 ARGF.set_encoding
已呼叫兩個編碼名稱,則會傳回第二個。否則,如果已設定 Encoding.default_external
,則會傳回該值。如果沒有,如果在命令列上指定了預設外部編碼,則會使用該值。如果編碼不明,則會傳回 nil
。
static VALUE argf_internal_encoding(VALUE argf) { return argf_encoding(argf, rb_io_internal_encoding); }
傳回 ARGF
的目前行號,為一個整體。這個值可以使用 ARGF.lineno=
手動設定。
例如
ARGF.lineno #=> 0 ARGF.readline #=> "This is line 1\n" ARGF.lineno #=> 1
static VALUE argf_lineno(VALUE argf) { return INT2FIX(ARGF.lineno); }
ARGF
會在您讀取資料時自動設定行號,因此通常不需要明確設定。若要存取目前的行號,請使用 ARGF.lineno
。
例如
ARGF.lineno #=> 0 ARGF.readline #=> "This is line 1\n" ARGF.lineno #=> 1 ARGF.lineno = 0 #=> 0 ARGF.lineno #=> 0
static VALUE argf_set_lineno(VALUE argf, VALUE val) { ARGF.lineno = NUM2INT(val); ARGF.last_lineno = ARGF.lineno; return val; }
傳回目前的檔案名稱。當目前的檔案為 STDIN 時,會傳回 “-”。
例如
$ echo "foo" > foo $ echo "bar" > bar $ echo "glark" > glark $ ruby argf.rb foo bar glark ARGF.filename #=> "foo" ARGF.read(5) #=> "foo\nb" ARGF.filename #=> "bar" ARGF.skip ARGF.filename #=> "glark"
傳回 ARGF
中目前檔案的目前偏移量(以位元組為單位)。
ARGF.pos #=> 0 ARGF.gets #=> "This is line one\n" ARGF.pos #=> 17
在 ARGF
中尋找到由 position(以位元組為單位)給定的位置。
例如
ARGF.pos = 17 ARGF.gets #=> "This is line two\n"
static VALUE argf_set_pos(VALUE argf, VALUE offset) { if (!next_argv()) { rb_raise(rb_eArgError, "no stream to set position"); } ARGF_FORWARD(1, &offset); return rb_io_set_pos(ARGF.current_file, offset); }
將給定的物件寫入串流;傳回 nil
。如果輸出記錄分隔符號 $OUTPUT_RECORD_SEPARATOR
($\
)不為 nil
,則會附加該分隔符號。請參閱 行 IO。
給定引數 objects
時,對於每個物件
-
如果它不是字串,則透過其方法
to_s
轉換。 -
寫入串流。
-
如果不是最後一個物件,則會寫入輸出欄位分隔符號
$OUTPUT_FIELD_SEPARATOR
($,
),如果它不為nil
。
使用預設分隔符號
f = File.open('t.tmp', 'w+') objects = [0, 0.0, Rational(0, 1), Complex(0, 0), :zero, 'zero'] p $OUTPUT_RECORD_SEPARATOR p $OUTPUT_FIELD_SEPARATOR f.print(*objects) f.rewind p f.read f.close
輸出
nil nil "00.00/10+0izerozero"
使用指定的符號
$\ = "\n" $, = ',' f.rewind f.print(*objects) f.rewind p f.read
輸出
"0,0.0,0/1,0+0i,zero,zero\n"
如果沒有給定引數,則會寫入 $_
的內容(通常是最近的使用者輸入)
f = File.open('t.tmp', 'w+') gets # Sets $_ to the most recent user input. f.print f.close
VALUE rb_io_print(int argc, const VALUE *argv, VALUE out) { int i; VALUE line; /* if no argument given, print `$_' */ if (argc == 0) { argc = 1; line = rb_lastline_get(); argv = &line; } if (argc > 1 && !NIL_P(rb_output_fs)) { rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value"); } for (i=0; i<argc; i++) { if (!NIL_P(rb_output_fs) && i>0) { rb_io_write(out, rb_output_fs); } rb_io_write(out, argv[i]); } if (argc > 0 && !NIL_P(rb_output_rs)) { rb_io_write(out, rb_output_rs); } return Qnil; }
格式化並將 objects
寫入串流。
有關 format_string
的詳細資訊,請參閱 格式規格。
VALUE rb_io_printf(int argc, const VALUE *argv, VALUE out) { rb_io_write(out, rb_f_sprintf(argc, argv)); return Qnil; }
將一個字元寫入串流。請參閱 字元 IO。
如果 object
是數字,則在必要時轉換為整數,然後寫入其代碼為最低有效位元的字元;如果 object
是字串,則寫入第一個字元
$stdout.putc "A" $stdout.putc 65
輸出
AA
static VALUE rb_io_putc(VALUE io, VALUE ch) { VALUE str; if (RB_TYPE_P(ch, T_STRING)) { str = rb_str_substr(ch, 0, 1); } else { char c = NUM2CHR(ch); str = rb_str_new(&c, 1); } rb_io_write(io, str); return ch; }
將指定的 objects
寫入串流,該串流必須開啟才能寫入;傳回 nil
。在每個尚未以換行序列結尾的項目後寫入換行。如果在沒有引數的情況下呼叫,則會寫入換行。請參閱 行 IO。
請注意,每個新增的換行都是字元 "\n"<//tt>,而不是輸出記錄分隔符 (<tt>$\
)。
每個物件的處理方式
-
字串:寫入字串。
-
既不是字串也不是陣列:寫入
object.to_s
。 -
陣列:寫入陣列的每個元素;陣列可以巢狀。
為了讓這些範例簡短,我們定義這個輔助方法
def show(*objects) # Puts objects to file. f = File.new('t.tmp', 'w+') f.puts(objects) # Return file content. f.rewind p f.read f.close end # Strings without newlines. show('foo', 'bar', 'baz') # => "foo\nbar\nbaz\n" # Strings, some with newlines. show("foo\n", 'bar', "baz\n") # => "foo\nbar\nbaz\n" # Neither strings nor arrays: show(0, 0.0, Rational(0, 1), Complex(9, 0), :zero) # => "0\n0.0\n0/1\n9+0i\nzero\n" # Array of strings. show(['foo', "bar\n", 'baz']) # => "foo\nbar\nbaz\n" # Nested arrays. show([[[0, 1], 2, 3], 4, 5]) # => "0\n1\n2\n3\n4\n5\n"
VALUE rb_io_puts(int argc, const VALUE *argv, VALUE out) { VALUE line, args[2]; /* if no argument given, print newline. */ if (argc == 0) { rb_io_write(out, rb_default_rs); return Qnil; } for (int i = 0; i < argc; i++) { // Convert the argument to a string: if (RB_TYPE_P(argv[i], T_STRING)) { line = argv[i]; } else if (rb_exec_recursive(io_puts_ary, argv[i], out)) { continue; } else { line = rb_obj_as_string(argv[i]); } // Write the line: int n = 0; if (RSTRING_LEN(line) == 0) { args[n++] = rb_default_rs; } else { args[n++] = line; if (!rb_str_end_with_asciichar(line, '\n')) { args[n++] = rb_default_rs; } } rb_io_writev(out, n, args); } return Qnil; }
從 ARGF
讀取 length 位元組。這個方法會將命令列上指定的檔案串接起來,並將它們視為一個單一檔案,因此在沒有引數的情況下呼叫時,會完整傳回這個偽檔案的內容。
length 必須是非負整數或 nil
。
如果 length 是正整數,read
會嘗試在沒有任何轉換的情況下讀取 length 位元組(二進位模式)。如果在可以讀取任何內容之前遇到 EOF,則會傳回 nil
。如果在讀取期間遇到 EOF,則會傳回少於 length 位元組。對於整數 length,產生的字串總是使用 ASCII-8BIT 編碼。
如果省略 length 或為 nil
,它會讀取到 EOF,並在適用的情況下套用編碼轉換。即使在讀取任何資料前遇到 EOF,也會傳回字串。
如果 length 為零,它會傳回空字串 (""
)。
如果存在選用的 outbuf 參數,它必須參考 String
,它會接收資料。即使 outbuf 在一開始並非為空,在方法呼叫後,它只會包含接收的資料。
例如
$ echo "small" > small.txt $ echo "large" > large.txt $ ./glark.rb small.txt large.txt ARGF.read #=> "small\nlarge" ARGF.read(200) #=> "small\nlarge" ARGF.read(2) #=> "sm" ARGF.read(0) #=> ""
請注意,這個方法的行為類似於 C 中的 fread() 函式。這表示它會重新嘗試呼叫 read(2) 系統呼叫,以讀取指定長度的資料。如果您需要類似於單一 read(2) 系統呼叫的行為,請考慮 ARGF#readpartial
或 ARGF#read_nonblock
。
static VALUE argf_read(int argc, VALUE *argv, VALUE argf) { VALUE tmp, str, length; long len = 0; rb_scan_args(argc, argv, "02", &length, &str); if (!NIL_P(length)) { len = NUM2LONG(argv[0]); } if (!NIL_P(str)) { StringValue(str); rb_str_resize(str,0); argv[1] = Qnil; } retry: if (!next_argv()) { return str; } if (ARGF_GENERIC_INPUT_P()) { tmp = argf_forward(argc, argv, argf); } else { tmp = io_read(argc, argv, ARGF.current_file); } if (NIL_P(str)) str = tmp; else if (!NIL_P(tmp)) rb_str_append(str, tmp); if (NIL_P(tmp) || NIL_P(length)) { if (ARGF.next_p != -1) { argf_close(argf); ARGF.next_p = 1; goto retry; } } else if (argc >= 1) { long slen = RSTRING_LEN(str); if (slen < len) { argv[0] = LONG2NUM(len - slen); goto retry; } } return str; }
從 ARGF
串流以非封鎖模式讀取最多 maxlen 位元組。
static VALUE argf_read_nonblock(int argc, VALUE *argv, VALUE argf) { VALUE opts; rb_scan_args(argc, argv, "11:", NULL, NULL, &opts); if (!NIL_P(opts)) argc--; return argf_getpartial(argc, argv, argf, opts, 1); }
從 ARGF
讀取下一個 8 位元組,並將其傳回為 Integer
。在讀取最後一個檔案的最後一個位元組後,會引發 EOFError
。
例如
$ echo "foo" > file $ ruby argf.rb file ARGF.readbyte #=> 102 ARGF.readbyte #=> 111 ARGF.readbyte #=> 111 ARGF.readbyte #=> 10 ARGF.readbyte #=> end of file reached (EOFError)
static VALUE argf_readbyte(VALUE argf) { VALUE c; NEXT_ARGF_FORWARD(0, 0); c = argf_getbyte(argf); if (NIL_P(c)) { rb_eof_error(); } return c; }
從 ARGF
讀取下一個字元,並將其傳回為 String
。在讀取最後一個檔案的最後一個字元後,會引發 EOFError
。
例如
$ echo "foo" > file $ ruby argf.rb file ARGF.readchar #=> "f" ARGF.readchar #=> "o" ARGF.readchar #=> "o" ARGF.readchar #=> "\n" ARGF.readchar #=> end of file reached (EOFError)
static VALUE argf_readchar(VALUE argf) { VALUE ch; retry: if (!next_argv()) rb_eof_error(); if (!RB_TYPE_P(ARGF.current_file, T_FILE)) { ch = forward_current(rb_intern("getc"), 0, 0); } else { ch = rb_io_getc(ARGF.current_file); } if (NIL_P(ch) && ARGF.next_p != -1) { argf_close(argf); ARGF.next_p = 1; goto retry; } return ch; }
傳回 ARGF
中目前檔案的下一行。
預設情況下,假設行是由 $/
分隔;若要使用不同的字元作為分隔符號,請提供 String
作為 sep 參數。
選用的 limit 參數指定要傳回每一行的字元數。預設情況下,會傳回所有字元。
在檔案結尾會引發 EOFError
。
static VALUE argf_readline(int argc, VALUE *argv, VALUE argf) { VALUE line; if (!next_argv()) rb_eof_error(); ARGF_FORWARD(argc, argv); line = argf_gets(argc, argv, argf); if (NIL_P(line)) { rb_eof_error(); } return line; }
讀取 ARGF
中的每個檔案,傳回包含檔案中行的 Array
。假設各行以 sep 分隔。
lines = ARGF.readlines lines[0] #=> "This is line one\n"
請參閱 IO.readlines
以取得所有選項的完整說明。
static VALUE argf_readlines(int argc, VALUE *argv, VALUE argf) { long lineno = ARGF.lineno; VALUE lines, ary; ary = rb_ary_new(); while (next_argv()) { if (ARGF_GENERIC_INPUT_P()) { lines = forward_current(rb_intern("readlines"), argc, argv); } else { lines = rb_io_readlines(argc, argv, ARGF.current_file); argf_close(argf); } ARGF.next_p = 1; rb_ary_concat(ary, lines); ARGF.lineno = lineno + RARRAY_LEN(ary); ARGF.last_lineno = ARGF.lineno; } ARGF.init_p = 0; return ary; }
從 ARGF
串流讀取最多 maxlen 位元組。
如果存在選用的 outbuf 參數,它必須參考 String
,它會接收資料。即使 outbuf 在一開始並非為空,在方法呼叫後,它只會包含接收的資料。
在 ARGF
串流結束時,會引發 EOFError
。由於 ARGF
串流是多個檔案的串接,因此內部會為每個檔案發生 EOF。ARGF.readpartial
會傳回空字串表示 EOF,但最後一個 EOF 除外,最後一個 EOF 會引發 EOFError
。
static VALUE argf_readpartial(int argc, VALUE *argv, VALUE argf) { return argf_getpartial(argc, argv, argf, Qnil, 0); }
將目前檔案定位到輸入的開頭,將 ARGF.lineno
重設為零。
ARGF.readline #=> "This is line one\n" ARGF.rewind #=> 0 ARGF.lineno #=> 0 ARGF.readline #=> "This is line one\n"
static VALUE argf_rewind(VALUE argf) { VALUE ret; int old_lineno; if (!next_argv()) { rb_raise(rb_eArgError, "no stream to rewind"); } ARGF_FORWARD(0, 0); old_lineno = RFILE(ARGF.current_file)->fptr->lineno; ret = rb_io_rewind(ARGF.current_file); if (!global_argf_p(argf)) { ARGF.last_lineno = ARGF.lineno -= old_lineno; } return ret; }
如果指定單一引數,從 ARGF
讀取的字串會標記為指定的編碼。
如果提供兩個由冒號分隔的編碼名稱,例如「ascii:utf-8」,讀取的字串會從第一個編碼(外部編碼)轉換為第二個編碼(內部編碼),然後標記為第二個編碼。
如果指定兩個引數,它們必須是編碼物件或編碼名稱。同樣地,第一個指定外部編碼;第二個指定內部編碼。
如果指定外部編碼和內部編碼,可以使用選用 Hash
引數來調整轉換程序。此雜湊的結構在 String#encode
文件中說明。
例如
ARGF.set_encoding('ascii') # Tag the input as US-ASCII text ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII # to UTF-8.
static VALUE argf_set_encoding(int argc, VALUE *argv, VALUE argf) { rb_io_t *fptr; if (!next_argv()) { rb_raise(rb_eArgError, "no stream to set encoding"); } rb_io_set_encoding(argc, argv, ARGF.current_file); GetOpenFile(ARGF.current_file, fptr); ARGF.encs = fptr->encs; return argf; }
將目前檔案設定為 ARGV 中的下一個檔案。如果沒有更多檔案,則不會產生任何作用。
例如
$ ruby argf.rb foo bar ARGF.filename #=> "foo" ARGF.skip ARGF.filename #=> "bar"
static VALUE argf_skip(VALUE argf) { if (ARGF.init_p && ARGF.next_p == 0) { argf_close(argf); ARGF.next_p = 1; } return argf; }
傳回 ARGF
中目前檔案的目前偏移量(以位元組為單位)。
ARGF.pos #=> 0 ARGF.gets #=> "This is line one\n" ARGF.pos #=> 17
static VALUE argf_tell(VALUE argf) { if (!next_argv()) { rb_raise(rb_eArgError, "no stream to tell"); } ARGF_FORWARD(0, 0); return rb_io_tell(ARGF.current_file); }
讀取 ARGF
中的每個檔案,傳回包含檔案中行的 Array
。假設各行以 sep 分隔。
lines = ARGF.readlines lines[0] #=> "This is line one\n"
請參閱 IO.readlines
以取得所有選項的完整說明。
傳回「ARGF」。
static VALUE argf_to_s(VALUE argf) { return rb_str_new2("ARGF"); }
如果已啟用就地模式,傳回繫結到 ARGF 的 IO
實例以進行寫入。
static VALUE argf_write_io(VALUE argf) { if (!RTEST(ARGF.current_file)) { rb_raise(rb_eIOError, "not opened for writing"); } return GetWriteIO(ARGF.current_file); }
如果為就地模式,寫入 string。
static VALUE argf_write(VALUE argf, VALUE str) { return rb_io_write(argf_write_io(argf), str); }