class StringIO
用于字符串的 IO 流,访问方式类似于 IO;请参见 IO。
关于示例¶ ↑
本页上的示例假设已 require 了 StringIO
require 'stringio'
常量
- MAX_LENGTH
-
一个
StringIO实例可以容纳的最大长度 - VERSION
-
版本字符串
公共类方法
源代码
static VALUE
strio_initialize(int argc, VALUE *argv, VALUE self)
{
struct StringIO *ptr = check_strio(self);
if (!ptr) {
DATA_PTR(self) = ptr = strio_alloc();
}
rb_call_super(0, 0);
return strio_init(argc, argv, ptr, self);
}
请注意,如果 string 被冻结,则 mode 默认为 'r'。
返回由 string 和 mode 构成的新 StringIO 实例;请参见 访问模式
strio = StringIO.new # => #<StringIO> strio.close
当不再需要该实例时,应将其关闭。
相关:StringIO.open (接受代码块;自动关闭)。
源代码
static VALUE
strio_s_open(int argc, VALUE *argv, VALUE klass)
{
VALUE obj = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
if (!rb_block_given_p()) return obj;
return rb_ensure(rb_yield, obj, strio_finalize, obj);
}
请注意,如果 string 被冻结,则 mode 默认为 'r'。
创建一个由 string 和 mode 构成的新 StringIO 实例;请参见 访问模式。
如果没有代码块,则返回新实例
strio = StringIO.open # => #<StringIO>
如果带有代码块,则使用新实例调用代码块,并返回代码块的值;在代码块退出时关闭实例。
StringIO.open {|strio| p strio } # => #<StringIO>
相关:StringIO.new。
公共实例方法
源代码
static VALUE
strio_binmode(VALUE self)
{
struct StringIO *ptr = StringIO(self);
rb_encoding *enc = rb_ascii8bit_encoding();
ptr->enc = enc;
if (WRITABLE(self)) {
rb_enc_associate(ptr->string, enc);
}
return self;
}
将 self 中的数据模式设置为二进制模式;请参见 数据模式。
源代码
static VALUE
strio_close(VALUE self)
{
StringIO(self);
RBASIC(self)->flags &= ~STRIO_READWRITE;
return Qnil;
}
关闭 self 进行读取和写入。
如果尝试读取或写入,则引发 IOError。
源代码
static VALUE
strio_close_read(VALUE self)
{
struct StringIO *ptr = StringIO(self);
if (!(ptr->flags & FMODE_READABLE)) {
rb_raise(rb_eIOError, "closing non-duplex IO for reading");
}
RBASIC(self)->flags &= ~STRIO_READABLE;
return Qnil;
}
关闭 self 进行读取;关闭写入设置保持不变。
如果尝试读取,则引发 IOError。
源代码
static VALUE
strio_close_write(VALUE self)
{
struct StringIO *ptr = StringIO(self);
if (!(ptr->flags & FMODE_WRITABLE)) {
rb_raise(rb_eIOError, "closing non-duplex IO for writing");
}
RBASIC(self)->flags &= ~STRIO_WRITABLE;
return Qnil;
}
关闭 self 进行写入;关闭读取设置保持不变。
如果尝试写入,则引发 IOError。
源代码
static VALUE
strio_closed(VALUE self)
{
StringIO(self);
if (!CLOSED(self)) return Qfalse;
return Qtrue;
}
如果 self 关闭以进行读取和写入,则返回 true,否则返回 false。
源代码
static VALUE
strio_closed_read(VALUE self)
{
StringIO(self);
if (READABLE(self)) return Qfalse;
return Qtrue;
}
如果 self 关闭以进行读取,则返回 true,否则返回 false。
源代码
static VALUE
strio_closed_write(VALUE self)
{
StringIO(self);
if (WRITABLE(self)) return Qfalse;
return Qtrue;
}
如果 self 关闭以进行写入,则返回 true,否则返回 false。
源代码
static VALUE
strio_each_byte(VALUE self)
{
struct StringIO *ptr;
RETURN_ENUMERATOR(self, 0, 0);
while ((ptr = strio_to_read(self)) != NULL) {
char c = RSTRING_PTR(ptr->string)[ptr->pos++];
rb_yield(CHR2FIX(c));
}
return self;
}
如果给定代码块,则使用流中剩余的每个字节调用该代码块;请参见 字节 IO。
如果没有给定代码块,则返回一个枚举器。
源代码
static VALUE
strio_each_char(VALUE self)
{
VALUE c;
RETURN_ENUMERATOR(self, 0, 0);
while (!NIL_P(c = strio_getc(self))) {
rb_yield(c);
}
return self;
}
如果给定代码块,则使用流中剩余的每个字符调用该代码块;请参见 字符 IO。
如果没有给定代码块,则返回一个枚举器。
源代码
static VALUE
strio_each_codepoint(VALUE self)
{
struct StringIO *ptr;
rb_encoding *enc;
unsigned int c;
int n;
RETURN_ENUMERATOR(self, 0, 0);
ptr = readable(self);
enc = get_enc(ptr);
while ((ptr = strio_to_read(self)) != NULL) {
c = rb_enc_codepoint_len(RSTRING_PTR(ptr->string)+ptr->pos,
RSTRING_END(ptr->string), &n, enc);
ptr->pos += n;
rb_yield(UINT2NUM(c));
}
return self;
}
如果给定代码块,则使用流中剩余的每个代码点调用该代码块;请参见 代码点 IO。
如果没有给定代码块,则返回一个枚举器。
源代码
static VALUE
strio_external_encoding(VALUE self)
{
struct StringIO *ptr = StringIO(self);
return rb_enc_from_encoding(get_enc(ptr));
}
返回表示文件编码的 Encoding 对象。如果流是写入模式且未指定编码,则返回 nil。
源代码
static VALUE
strio_unimpl(int argc, VALUE *argv, VALUE self)
{
StringIO(self);
rb_notimplement();
UNREACHABLE;
}
源代码
static VALUE
strio_nil(VALUE self)
{
StringIO(self);
return Qnil;
}
返回 nil。仅用于与 IO 的兼容性。
源代码
static VALUE
strio_self(VALUE self)
{
StringIO(self);
return self;
}
返回对象本身。仅用于与 IO 的兼容性。
源代码
static VALUE
strio_0(VALUE self)
{
StringIO(self);
return INT2FIX(0);
}
返回 0。仅用于与 IO 的兼容性。
源代码
static VALUE
strio_getbyte(VALUE self)
{
struct StringIO *ptr = readable(self);
int c;
if (NIL_P(ptr->string) || ptr->pos >= RSTRING_LEN(ptr->string)) {
return Qnil;
}
c = RSTRING_PTR(ptr->string)[ptr->pos++];
return CHR2FIX(c);
}
从流中读取并返回下一个 8 位字节;请参见 字节 IO。
源代码
static VALUE
strio_getc(VALUE self)
{
struct StringIO *ptr = readable(self);
rb_encoding *enc = get_enc(ptr);
VALUE str = ptr->string;
long pos = ptr->pos;
int len;
char *p;
if (NIL_P(str) || pos >= RSTRING_LEN(str)) {
return Qnil;
}
p = RSTRING_PTR(str)+pos;
len = rb_enc_mbclen(p, RSTRING_END(str), enc);
ptr->pos += len;
return enc_subseq(str, pos, len, enc);
}
从流中读取并返回下一个字符;请参见 字符 IO。
源代码
static VALUE
strio_gets(int argc, VALUE *argv, VALUE self)
{
struct StringIO *ptr = readable(self);
struct getline_arg arg;
VALUE str;
if (prepare_getline_args(ptr, &arg, argc, argv)->limit == 0) {
if (NIL_P(ptr->string)) return Qnil;
return rb_enc_str_new(0, 0, get_enc(ptr));
}
str = strio_getline(&arg, ptr);
rb_lastline_set(str);
return str;
}
从流中读取并返回一行;将返回值赋给 $_;请参见 行 IO。
源代码
static VALUE
strio_internal_encoding(VALUE self)
{
return Qnil;
}
如果指定了转换,则返回内部字符串的 Encoding。否则返回 nil。
源代码
static VALUE
strio_false(VALUE self)
{
StringIO(self);
return Qfalse;
}
返回 false。仅用于与 IO 的兼容性。
源代码
static VALUE
strio_get_lineno(VALUE self)
{
return LONG2NUM(StringIO(self)->lineno);
}
返回 self 中的当前行号;请参见 行号。
源代码
static VALUE
strio_set_lineno(VALUE self, VALUE lineno)
{
StringIO(self)->lineno = NUM2LONG(lineno);
return lineno;
}
将 self 中的当前行号设置为给定的 new_line_number;请参见 行号。
源代码
static VALUE
strio_get_pos(VALUE self)
{
return LONG2NUM(StringIO(self)->pos);
}
返回当前位置(以字节为单位);请参见 位置。
源代码
static VALUE
strio_set_pos(VALUE self, VALUE pos)
{
struct StringIO *ptr = StringIO(self);
long p = NUM2LONG(pos);
if (p < 0) {
error_inval(0);
}
ptr->pos = p;
return pos;
}
设置当前位置(以字节为单位);请参见 位置。
源代码
static VALUE
strio_pread(int argc, VALUE *argv, VALUE self)
{
VALUE rb_len, rb_offset, rb_buf;
rb_scan_args(argc, argv, "21", &rb_len, &rb_offset, &rb_buf);
long len = NUM2LONG(rb_len);
long offset = NUM2LONG(rb_offset);
if (len < 0) {
rb_raise(rb_eArgError, "negative string size (or size too big): %" PRIsVALUE, rb_len);
}
if (len == 0) {
if (NIL_P(rb_buf)) {
return rb_str_new("", 0);
}
return rb_buf;
}
if (offset < 0) {
rb_syserr_fail_str(EINVAL, rb_sprintf("pread: Invalid offset argument: %" PRIsVALUE, rb_offset));
}
struct StringIO *ptr = readable(self);
if (offset >= RSTRING_LEN(ptr->string)) {
rb_eof_error();
}
if (NIL_P(rb_buf)) {
return strio_substr(ptr, offset, len, rb_ascii8bit_encoding());
}
long 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;
}
请参见 IO#pread。
源代码
static VALUE
strio_putc(VALUE self, VALUE ch)
{
struct StringIO *ptr = writable(self);
VALUE str;
check_modifiable(ptr);
if (RB_TYPE_P(ch, T_STRING)) {
if (NIL_P(ptr->string)) return ch;
str = rb_str_substr(ch, 0, 1);
}
else {
char c = NUM2CHR(ch);
if (NIL_P(ptr->string)) return ch;
str = rb_str_new(&c, 1);
}
strio_write(self, str);
return ch;
}
请参见 IO#putc。
源代码
static VALUE
strio_read(int argc, VALUE *argv, VALUE self)
{
struct StringIO *ptr = readable(self);
VALUE str = Qnil;
long len;
int binary = 0;
switch (argc) {
case 2:
str = argv[1];
if (!NIL_P(str)) {
StringValue(str);
rb_str_modify(str);
}
/* fall through */
case 1:
if (!NIL_P(argv[0])) {
len = NUM2LONG(argv[0]);
if (len < 0) {
rb_raise(rb_eArgError, "negative length %ld given", len);
}
if (len > 0 &&
(NIL_P(ptr->string) || ptr->pos >= RSTRING_LEN(ptr->string))) {
if (!NIL_P(str)) rb_str_resize(str, 0);
return Qnil;
}
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 {
long 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;
}
请参见 IO#read。
源代码
static VALUE
strio_readlines(int argc, VALUE *argv, VALUE self)
{
VALUE ary, line;
struct StringIO *ptr = readable(self);
struct getline_arg arg;
if (prepare_getline_args(ptr, &arg, argc, argv)->limit == 0) {
rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
}
ary = rb_ary_new();
while (!NIL_P(line = strio_getline(&arg, ptr))) {
rb_ary_push(ary, line);
}
return ary;
}
请参见 IO#readlines。
源代码
static VALUE
strio_reopen(int argc, VALUE *argv, VALUE self)
{
rb_io_taint_check(self);
if (argc == 1 && !RB_TYPE_P(*argv, T_STRING)) {
return strio_copy(self, *argv);
}
return strio_init(argc, argv, StringIO(self), self);
}
使用给定的 other (字符串或 StringIO) 和 mode 重新初始化流;请参见 IO.new
StringIO.open('foo') do |strio| p strio.string strio.reopen('bar') p strio.string other_strio = StringIO.new('baz') strio.reopen(other_strio) p strio.string other_strio.close end
输出
"foo" "bar" "baz"
源代码
源代码
static VALUE
strio_seek(int argc, VALUE *argv, VALUE self)
{
VALUE whence;
struct StringIO *ptr = StringIO(self);
long amount, offset;
rb_scan_args(argc, argv, "11", NULL, &whence);
amount = NUM2LONG(argv[0]);
if (CLOSED(self)) {
rb_raise(rb_eIOError, "closed stream");
}
switch (NIL_P(whence) ? 0 : NUM2LONG(whence)) {
case 0:
offset = 0;
break;
case 1:
offset = ptr->pos;
break;
case 2:
offset = RSTRING_LEN(ptr->string);
break;
default:
error_inval("invalid whence");
}
if (amount > LONG_MAX - offset || amount + offset < 0) {
error_inval(0);
}
ptr->pos = amount + offset;
return INT2FIX(0);
}
将当前位置设置为给定的整数 offset(以字节为单位),相对于给定的常量 whence;请参见 位置。
源代码
static VALUE
strio_set_encoding(int argc, VALUE *argv, VALUE self)
{
rb_encoding* enc;
struct StringIO *ptr = StringIO(self);
VALUE ext_enc, int_enc, opt;
argc = rb_scan_args(argc, argv, "11:", &ext_enc, &int_enc, &opt);
if (NIL_P(ext_enc)) {
enc = rb_default_external_encoding();
}
else {
enc = rb_find_encoding(ext_enc);
if (!enc) {
rb_io_enc_t convconfig;
int oflags, fmode;
VALUE vmode = rb_str_append(rb_str_new_cstr("r:"), ext_enc);
rb_io_extract_modeenc(&vmode, 0, Qnil, &oflags, &fmode, &convconfig);
enc = convconfig.enc2;
}
}
ptr->enc = enc;
if (!NIL_P(ptr->string) && WRITABLE(self)) {
rb_enc_associate(ptr->string, enc);
}
return self;
}
将 StringIO 的编码指定为 ext_enc。如果 ext_enc 为 nil,则使用默认的外部编码。第二个参数 int_enc 和可选的哈希 opt 参数将被忽略;它们用于与 IO 的 API 兼容性。
源代码
static VALUE
strio_set_encoding_by_bom(VALUE self)
{
struct StringIO *ptr = StringIO(self);
if (!set_encoding_by_bom(ptr)) return Qnil;
return rb_enc_from_encoding(ptr->enc);
}
根据字符串中的 BOM (字节顺序标记) 设置编码。
如果找到 BOM,则返回 self,否则返回 +nil。
源代码
static VALUE
strio_size(VALUE self)
{
VALUE string = StringIO(self)->string;
if (NIL_P(string)) {
return INT2FIX(0);
}
return ULONG2NUM(RSTRING_LEN(string));
}
返回缓冲区字符串的大小。
源代码
static VALUE
strio_get_string(VALUE self)
{
return StringIO(self)->string;
}
返回底层字符串
StringIO.open('foo') do |strio| p strio.string strio.string = 'bar' p strio.string end
输出
"foo" "bar"
相关:StringIO#string= (分配底层字符串)。
源代码
static VALUE
strio_set_string(VALUE self, VALUE string)
{
struct StringIO *ptr = StringIO(self);
rb_io_taint_check(self);
ptr->flags &= ~FMODE_READWRITE;
StringValue(string);
ptr->flags = readonly_string_p(string) ? FMODE_READABLE : FMODE_READWRITE;
ptr->pos = 0;
ptr->lineno = 0;
RB_OBJ_WRITE(self, &ptr->string, string);
return string;
}
将底层字符串赋值为 other_string,并将位置设置为零;返回 other_string
StringIO.open('foo') do |strio| p strio.string strio.string = 'bar' p strio.string end
输出
"foo" "bar"
相关:StringIO#string (返回底层字符串)。
源代码
static VALUE
strio_get_sync(VALUE self)
{
StringIO(self);
return Qtrue;
}
返回 true;仅为与其他流类的兼容性而实现。
源代码
static VALUE
strio_first(VALUE self, VALUE arg)
{
StringIO(self);
return arg;
}
返回未更改的参数。仅用于与 IO 的兼容性。
源代码
static VALUE
strio_get_pos(VALUE self)
{
return LONG2NUM(StringIO(self)->pos);
}
返回当前位置(以字节为单位);请参见 位置。
源代码
static VALUE
strio_truncate(VALUE self, VALUE len)
{
VALUE string = writable(self)->string;
long l = NUM2LONG(len);
long plen;
if (l < 0) {
error_inval("negative length");
}
if (NIL_P(string)) return 0;
plen = RSTRING_LEN(string);
rb_str_resize(string, l);
if (plen < l) {
MEMZERO(RSTRING_PTR(string) + plen, char, l - plen);
}
return INT2FIX(0);
}
将缓冲区字符串截断为最多 integer 字节。流必须打开以进行写入。
源代码
static VALUE
strio_ungetbyte(VALUE self, VALUE c)
{
struct StringIO *ptr = readable(self);
check_modifiable(ptr);
if (NIL_P(ptr->string)) return Qnil;
if (NIL_P(c)) return Qnil;
if (RB_INTEGER_TYPE_P(c)) {
/* rb_int_and() not visible from exts */
VALUE v = rb_funcall(c, '&', 1, INT2FIX(0xff));
const char cc = NUM2INT(v) & 0xFF;
strio_unget_bytes(ptr, &cc, 1);
}
else {
StringValue(c);
strio_unget_string(ptr, c);
}
return Qnil;
}
将 8 位字节推回(“取消移动”)到流上;请参见 字节 IO。
源代码
static VALUE
strio_ungetc(VALUE self, VALUE c)
{
struct StringIO *ptr = readable(self);
rb_encoding *enc, *enc2;
check_modifiable(ptr);
if (NIL_P(ptr->string)) return Qnil;
if (NIL_P(c)) return Qnil;
if (RB_INTEGER_TYPE_P(c)) {
int len, cc = NUM2INT(c);
char buf[16];
enc = rb_enc_get(ptr->string);
len = rb_enc_codelen(cc, enc);
if (len <= 0) {
rb_enc_uint_chr(cc, enc); /* to raise an exception */
UNREACHABLE;
}
rb_enc_mbcput(cc, buf, enc);
return strio_unget_bytes(ptr, buf, len);
}
else {
StringValue(c);
if (RSTRING_LEN(c) == 0) return Qnil;
enc = rb_enc_get(ptr->string);
enc2 = rb_enc_get(c);
if (enc != enc2 && enc != rb_ascii8bit_encoding()) {
c = rb_str_conv_enc(c, enc2, enc);
}
strio_unget_string(ptr, c);
return Qnil;
}
}
将字符或整数推回(“取消移动”)到流上;请参见 字符 IO。
源代码
static VALUE
strio_write_m(int argc, VALUE *argv, VALUE self)
{
long len = 0;
while (argc-- > 0) {
/* StringIO can't exceed long limit */
len += strio_write(self, *argv++);
}
return LONG2NUM(len);
}
将给定的字符串追加到底层缓冲区字符串。流必须打开以进行写入。如果参数不是字符串,则将使用 to_s 将其转换为字符串。返回写入的字节数。请参见 IO#write。