Kernel#putc
putc(obj) -> obj The putc method outputs a single character to STDOUT. Unlike puts which outputs strings with a newline, putc writes exactly one character and returns the object that was passed to it.
How it differs from puts
puts "hello" # Outputs: hello\n and returns nil
putc "hello" # Outputs: h and returns "hello"
puts "A" # Outputs: A\n
putc "A" # Outputs: A
Unlike puts which adds a trailing newline, putc writes exactly one character and stops. When given a multi-character string, it outputs only the first character. The return value is also different: putc returns its argument object, while puts always returns nil.
Practical examples
Basic character output
# Output a single character
putc "A" # Prints: A
# With integers - outputs the character with that ASCII code
putc 65 # Prints: A (ASCII 65)
putc 97 # Prints: a (ASCII 97)
putc 10 # Prints: newline
# String input - only first character
putc "hello" # Prints: h
When you pass an integer, putc interprets it as an ASCII code and outputs the corresponding character. This is useful for low-level byte manipulation where you work with numeric codes rather than string literals. Passing a string outputs only the first character of that string.
Building output character by character
# Create a progress indicator
progress = ["|", "/", "-", "\\"]
5.times do |i|
print "\rProcessing #{progress[i % 4]}"
putc "\r" # Carriage return to overwrite
sleep 0.5
end
puts "\nDone!"
This progress indicator pattern uses \r (carriage return) to overwrite the current line, creating a spinning animation. The print method outputs the frame without a newline, and the carriage return brings the cursor back to the start of the line for the next frame. After the loop finishes, puts adds a final newline.
Writing to a file
# Putc works with any IO object
File.open("output.txt", "w") do |f|
putc f, "H"
putc f, "i"
putc f, "\n"
end
# File contains: Hi
putc accepts an optional IO object as the first argument, which lets you write to files, sockets, or any other writable stream. When the first argument is an IO object, the character is written to that stream instead of STDOUT.
Low-level character handling
# Convert number to character
putc 0x41 # Hex 41 = 65 = 'A', outputs: A
# Binary data handling
bytes = [0x48, 0x65, 0x6C, 0x6C, 0x6F]
bytes.each { |b| putc b }
# Outputs: Hello
# Output character from variable
char = "X"
putc char # Outputs: X
When you need to output raw byte values, passing integers to putc is more direct than constructing strings. The loop over hex values demonstrates how you can convert a sequence of byte codes into visible characters without any intermediate string allocation.
Color output in terminal
# ANSI escape codes for colors
RED = "\e[31m"
RESET = "\e[0m"
putc RED[0]
putc "R"[0]
putc RESET[0]
puts # Newline to complete
ANSI escape codes are multi-byte sequences that control terminal formatting. Using putc for individual characters gives you fine-grained control over the escape sequence, though in practice you would normally output the entire sequence as a string with print or puts.
Return value
# putc returns the object passed to it
result = putc "hello"
puts result # => hello
# This allows chaining (though unusual)
putc(putc("A")) # Outputs: AA, returns "A"
Common uses
putc is useful when you need:
- Character-by-character output
- Building output incrementally
- Working with binary data
- Low-level terminal operations
It’s a lower-level method than puts or print, giving you direct control over exactly what bytes are written to the output stream.
Writing one character at a time
putc is useful when the output needs to be very small and very direct. It fits terminal effects, byte-oriented output, and examples where the code wants to show exactly one character at a time. That makes it a lower-level tool than puts, but also a more precise one. The call site should be clear about that choice so the reader knows the method is writing a single character on purpose.
Because putc works one character at a time, it is usually best kept for very focused output. That might be a cursor effect, a byte dump, or a tiny terminal demo where the point is to show exact control over the stream. For ordinary messages, puts or print are easier to read, but putc is a nice fit when the code really does need that lower-level detail.
The method is also a reminder that output formatting and output transport are separate concerns. putc handles the transport very literally, while the surrounding code decides what the character means. That can be useful in small demos or tooling where one byte at a time is the right unit of work and the display logic stays intentionally simple.