Preview Ruby 4.1 is a preview. It can change before the final release. Switch to Ruby 4.0 →
StringIO#pread
static VALUE
strio_pread(int argc, VALUE *argv, VALUE self)
{
VALUE rb_len, rb_offset, rb_buf;
struct StringIO *ptr = readable(self);
rb_scan_args(argc, argv, "21", &rb_len, &rb_offset, &rb_buf);
rb_len_t len = NUM2LEN(rb_len);
rb_len_t offset = NUM2LEN(rb_offset);
if (len < 0) {
rb_raise(rb_eArgError, "negative string size (or size too big): %" PRIsVALUE, rb_len);
}
if (offset < 0) {
rb_syserr_fail_str(EINVAL, rb_sprintf("pread: Invalid offset argument: %" PRIsVALUE, rb_offset));
}
rb_buf = strio_readbuf(ptr, rb_buf);
if (len == 0) {
if (NIL_P(rb_buf)) {
return rb_str_new("", 0);
}
return rb_buf;
}
if (outside_p(ptr, offset)) {
rb_eof_error();
}
if (NIL_P(rb_buf)) {
return strio_substr(ptr, offset, len, rb_ascii8bit_encoding());
}
rb_len_t rest = RSTRING_LEN(ptr->string) - offset;
if (len > rest) len = rest;
rb_str_resize(rb_buf, len);
rb_enc_associate(rb_buf, rb_ascii8bit_encoding());
MEMCPY(RSTRING_PTR(rb_buf), RSTRING_PTR(ptr->string) + offset, char, len);
return rb_buf;
}
Note: Method pread is different from other reading methods in that it does not modify self in any way; thus, multiple threads may read safely from the same stream.
Reads up to maxlen bytes from the stream, beginning at 0-based byte offset offset; returns a string containing the read bytes.
The returned string:
-
Contains
maxlenbytes from the stream, if available; otherwise contains all available bytes. -
Has encoding
Encoding::ASCII_8BIT.
With only arguments maxlen and offset given, returns a new string:
english = 'Hello' # Five 1-byte characters. strio = StringIO.new(english) strio.pread(3, 0) # => "Hel" strio.pread(3, 2) # => "llo" strio.pread(0, 0) # => "" strio.pread(50, 0) # => "Hello" strio.pread(50, 2) # => "llo" strio.pread(50, 4) # => "o" strio.pread(0, 0).encoding # => #<Encoding:BINARY (ASCII-8BIT)> russian = 'Привет' # Six 2-byte characters. strio = StringIO.new(russian) strio.pread(50, 0) # All 12 bytes. # => "\xD0\x9F\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82" strio.pread(3, 0) # => "\xD0\x9F\xD1" strio.pread(3, 3) # => "\x80\xD0\xB8" strio.pread(0, 0).encoding # => #<Encoding:BINARY (ASCII-8BIT)> japanese = 'こんにちは' # Five 3-byte characters. strio = StringIO.new(japanese) strio.pread(50, 0) # All 15 bytes. # => "\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1\xE3\x81\xAF" strio.pread(6, 0) # => "\xE3\x81\x93\xE3\x82\x93" strio.pread(1, 2) # => "\x93" strio.pread(0, 0).encoding # => #<Encoding:BINARY (ASCII-8BIT)>
Raises an exception if offset is out-of-range:
strio = StringIO.new(english) strio.pread(5, 50) # Raises EOFError: end of file reached
With string argument out_string given:
-
Reads as above.
-
Overwrites the content of
out_stringwith the read bytes.
Examples:
out_string = 'Will be overwritten' out_string.encoding # => #<Encoding:UTF-8> result = StringIO.new(english).pread(50, 0, out_string) result.__id__ == out_string.__id__ # => true out_string # => "Hello" out_string.encoding # => #<Encoding:BINARY (ASCII-8BIT)>