Overview
Package bufio implements buffered I/O. It wraps an io.Reader or io.Writer object, creating another object (Reader or Writer) that also implements the interface but provides buffering and some help for textual I/O.
Buffered Reading
NewReader
Returns a new Reader whose buffer has the default size (4096 bytes).
func NewReader(rd io.Reader) *Reader
Underlying reader to buffer
Example:
file, _ := os.Open("data.txt")
defer file.Close()
reader := bufio.NewReader(file)
line, _ := reader.ReadString('\n')
fmt.Print(line)
NewReaderSize
Returns a new Reader whose buffer has at least the specified size.
func NewReaderSize(rd io.Reader, size int) *Reader
Example:
reader := bufio.NewReaderSize(file, 8192) // 8KB buffer
Reader.Read
Reads data into p.
func (b *Reader) Read(p []byte) (n int, err error)
Reader.ReadByte
Reads and returns a single byte.
func (b *Reader) ReadByte() (byte, error)
Example:
b, err := reader.ReadByte()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Read byte: %c\n", b)
Reader.ReadString
Reads until the first occurrence of delim in the input.
func (b *Reader) ReadString(delim byte) (string, error)
Delimiter byte to read until
String containing data up to and including the delimiter
Example:
line, err := reader.ReadString('\n')
if err != nil && err != io.EOF {
log.Fatal(err)
}
fmt.Print(line)
Reader.ReadBytes
Reads until the first occurrence of delim, returning a byte slice.
func (b *Reader) ReadBytes(delim byte) ([]byte, error)
Example:
data, err := reader.ReadBytes('\n')
Reader.ReadLine
Low-level line-reading primitive. Most callers should use ReadBytes(‘\n’) or ReadString(‘\n’) instead.
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)
Line data (without newline)
True if line was too long for buffer
Reader.Peek
Returns the next n bytes without advancing the reader.
func (b *Reader) Peek(n int) ([]byte, error)
Example:
data, err := reader.Peek(10)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Next 10 bytes: %s\n", data)
Reader.Buffered
Returns the number of bytes that can be read from the current buffer.
func (b *Reader) Buffered() int
Example:
n := reader.Buffered()
fmt.Printf("%d bytes buffered\n", n)
Buffered Writing
NewWriter
Returns a new Writer whose buffer has the default size.
func NewWriter(w io.Writer) *Writer
Underlying writer to buffer
Example:
file, _ := os.Create("output.txt")
defer file.Close()
writer := bufio.NewWriter(file)
writer.WriteString("Hello, World!\n")
writer.Flush() // Important: flush to write buffered data
NewWriterSize
Returns a new Writer whose buffer has at least the specified size.
func NewWriterSize(w io.Writer, size int) *Writer
Writer.Write
Writes the contents of p into the buffer.
func (b *Writer) Write(p []byte) (nn int, err error)
Writer.WriteByte
Writes a single byte.
func (b *Writer) WriteByte(c byte) error
Example:
err := writer.WriteByte('A')
Writer.WriteString
Writes a string.
func (b *Writer) WriteString(s string) (int, error)
Example:
n, err := writer.WriteString("Hello, World!\n")
if err != nil {
log.Fatal(err)
}
Writer.WriteRune
Writes a single Unicode code point.
func (b *Writer) WriteRune(r rune) (size int, err error)
Example:
size, err := writer.WriteRune('世')
Writer.Flush
Writes any buffered data to the underlying io.Writer.
func (b *Writer) Flush() error
Example:
writer.WriteString("data")
err := writer.Flush() // Ensure data is written
if err != nil {
log.Fatal(err)
}
Writer.Available
Returns how many bytes are unused in the buffer.
func (b *Writer) Available() int
Writer.Buffered
Returns the number of bytes that have been written into the current buffer.
func (b *Writer) Buffered() int
Scanner
NewScanner
Returns a new Scanner to read from r.
func NewScanner(r io.Reader) *Scanner
Example:
file, _ := os.Open("data.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
Scanner.Scan
Advances the Scanner to the next token.
func (s *Scanner) Scan() bool
True if there is a token to read
Scanner.Text
Returns the most recent token as a string.
func (s *Scanner) Text() string
Example:
for scanner.Scan() {
line := scanner.Text()
fmt.Println(line)
}
Scanner.Bytes
Returns the most recent token as a byte slice.
func (s *Scanner) Bytes() []byte
Scanner.Err
Returns the first non-EOF error encountered by the Scanner.
func (s *Scanner) Err() error
Example:
for scanner.Scan() {
// process
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
Scanner.Split
Sets the split function for the Scanner.
func (s *Scanner) Split(split SplitFunc)
Function to tokenize input. Default is ScanLines.
Example:
scanner := bufio.NewScanner(reader)
scanner.Split(bufio.ScanWords) // Split on words instead of lines
for scanner.Scan() {
word := scanner.Text()
fmt.Println(word)
}
Split Functions
Predefined split functions for Scanner:
- ScanBytes - Returns each byte as a token
- ScanRunes - Returns each UTF-8 encoded rune as a token
- ScanWords - Returns each space-separated word as a token
- ScanLines - Returns each newline-terminated line as a token (default)
Complete Example
package main
import (
"bufio"
"fmt"
"log"
"os"
"strings"
)
func main() {
// Writing with bufio
file, err := os.Create("output.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
writer := bufio.NewWriter(file)
writer.WriteString("Line 1\n")
writer.WriteString("Line 2\n")
writer.WriteString("Line 3\n")
writer.Flush() // Important!
// Reading line by line
file, _ = os.Open("output.txt")
defer file.Close()
reader := bufio.NewReader(file)
for {
line, err := reader.ReadString('\n')
if err != nil {
break
}
fmt.Print(line)
}
// Using Scanner
input := "word1 word2 word3"
scanner := bufio.NewScanner(strings.NewReader(input))
scanner.Split(bufio.ScanWords)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}
- Always call
Flush() on Writer before closing the underlying writer
- Use Scanner for simple line-by-line or word-by-word reading
- Use Reader methods for more control over buffering
- Adjust buffer size with NewReaderSize/NewWriterSize for optimal performance
- Scanner is more convenient but Reader gives more control