Maintenance Ruby 3.4 gets fixes, but no new features. Switch to Ruby 4.0 →
instance method
IO#ungetc
(::String object) -> nil
ungetc(integer) → nil
ungetc(string) → nil
io.c
View on GitHub ↗
VALUE
rb_io_ungetc(VALUE io, VALUE c)
{
rb_io_t *fptr;
long len;
GetOpenFile(io, fptr);
rb_io_check_char_readable(fptr);
if (FIXNUM_P(c)) {
c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
}
else if (RB_BIGNUM_TYPE_P(c)) {
c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
}
else {
StringValue(c);
}
if (NEED_READCONV(fptr)) {
SET_BINARY_MODE(fptr);
len = RSTRING_LEN(c);
#if SIZEOF_LONG > SIZEOF_INT
if (len > INT_MAX)
rb_raise(rb_eIOError, "ungetc failed");
#endif
make_readconv(fptr, (int)len);
if (fptr->cbuf.capa - fptr->cbuf.len < len)
rb_raise(rb_eIOError, "ungetc failed");
if (fptr->cbuf.off < len) {
MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
fptr->cbuf.ptr+fptr->cbuf.off,
char, fptr->cbuf.len);
fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
}
fptr->cbuf.off -= (int)len;
fptr->cbuf.len += (int)len;
MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
}
else {
NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
io_ungetbyte(c, fptr);
}
return Qnil;
}
Pushes back (“unshifts”) the given data onto the stream’s buffer, placing the data so that it is next to be read; returns nil. See Character IO.
Note that:
-
Calling the method has no effect with unbuffered reads (such as
IO#sysread). -
Calling
rewindon the stream discards the pushed-back data.
When argument integer is given, interprets the integer as a character:
Example
File.write('t.tmp', '012') f = File.open('t.tmp') f.ungetc(0x41) # => nil f.read # => "A012" f.rewind f.ungetc(0x0442) # => nil f.getc.ord # => 1090 f.close
When argument string is given, uses all characters:
Example
File.write('t.tmp', '012') f = File.open('t.tmp') f.ungetc('A') # => nil f.read # => "A012" f.rewind f.ungetc("\u0442\u0435\u0441\u0442") # => nil f.getc.ord # => 1090 f.getc.ord # => 1077 f.getc.ord # => 1089 f.getc.ord # => 1090 f.close