Preview Ruby 4.1 is a preview. It can change before the final release. Switch to Ruby 4.0 →
StringIO#read
static VALUE
strio_read(int argc, VALUE *argv, VALUE self)
{
struct StringIO *ptr = readable(self);
VALUE str = Qnil;
rb_len_t len;
int binary = 0;
switch (argc) {
case 2:
str = strio_readbuf(ptr, argv[1]);
/* fall through */
case 1:
if (!NIL_P(argv[0])) {
len = NUM2LEN(argv[0]);
if (len < 0) {
rb_raise(rb_eArgError, "negative length %"PRIdLEN" given", len);
}
if (eos_p(ptr)) {
if (!NIL_P(str)) rb_str_resize(str, 0);
return len > 0 ? Qnil : rb_str_new(0, 0);
}
binary = 1;
break;
}
/* fall through */
case 0:
if (NIL_P(ptr->string)) return Qnil;
len = RSTRING_LEN(ptr->string);
if (len <= ptr->pos) {
rb_encoding *enc = get_enc(ptr);
if (NIL_P(str)) {
str = rb_str_new(0, 0);
}
else {
rb_str_resize(str, 0);
}
rb_enc_associate(str, enc);
return str;
}
else {
len -= ptr->pos;
}
break;
default:
rb_error_arity(argc, 0, 2);
}
if (NIL_P(str)) {
rb_encoding *enc = binary ? rb_ascii8bit_encoding() : get_enc(ptr);
str = strio_substr(ptr, ptr->pos, len, enc);
}
else {
rb_len_t rest = RSTRING_LEN(ptr->string) - ptr->pos;
if (len > rest) len = rest;
rb_str_resize(str, len);
MEMCPY(RSTRING_PTR(str), RSTRING_PTR(ptr->string) + ptr->pos, char, len);
if (!binary) {
rb_enc_copy(str, ptr->string);
}
}
ptr->pos += RSTRING_LEN(str);
return str;
}
Reads and returns a string containing bytes read from the stream, beginning at the current position; advances the position by the count of bytes read.
With no arguments given, reads all remaining bytes in the stream; returns a new string containing bytes read:
strio = StringIO.new('Hello') # Five 1-byte characters. strio.read # => "Hello" strio.pos # => 5 strio.read # => "" StringIO.new('').read # => ""
With non-negative argument maxlen given, reads maxlen bytes as available; returns a new string containing the bytes read, or nil if none:
strio.rewind strio.read(3) # => "Hel" strio.read(3) # => "lo" strio.read(3) # => nil russian = 'Привет' # Six 2-byte characters. russian.b # => "\xD0\x9F\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82" strio = StringIO.new(russian) strio.read(6) # => "\xD0\x9F\xD1\x80\xD0\xB8" strio.read(6) # => "\xD0\xB2\xD0\xB5\xD1\x82" strio.read(6) # => nil japanese = 'こんにちは' japanese.b # => "\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1\xE3\x81\xAF" strio = StringIO.new(japanese) strio.read(9) # => "\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB" strio.read(9) # => "\xE3\x81\xA1\xE3\x81\xAF" strio.read(9) # => nil
With argument max_len as nil and string argument out_string given, reads the remaining bytes in the stream; clears out_string and writes the bytes into it; returns out_string:
out_string = 'Will be overwritten' strio = StringIO.new('Hello') strio.read(nil, out_string) # => "Hello" strio.read(nil, out_string) # => ""
With non-negative argument maxlen and string argument out_string given, reads the +maxlen bytes from the stream, as availble; clears out_string and writes the bytes into it; returns out_string if any bytes were read, or nil if none:
out_string = 'Will be overwritten' strio = StringIO.new('Hello') strio.read(3, out_string) # => "Hel" strio.read(3, out_string) # => "lo" strio.read(3, out_string) # => nil out_string = 'Will be overwritten' strio = StringIO.new(russian) strio.read(6, out_string) # => "При" strio.read(6, out_string) # => "вет" strio.read(6, out_string) # => nil strio.rewind russian.b # => "\xD0\x9F\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82" strio.read(3) # => "\xD0\x9F\xD1" strio.read(3) # => "\x80\xD0\xB8" out_string = 'Will be overwritten' strio = StringIO.new(japanese) strio.read(9, out_string) # => "こんに" strio.read(9, out_string) # => "ちは" strio.read(9, out_string) # => nil strio.rewind japanese.b # => "\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1\xE3\x81\xAF" strio.read(4) # => "\xE3\x81\x93\xE3" strio.read(4) # => "\x82\x93\xE3\x81"