---
title: "std.io Buffered (BufferedReader/BufferedWriter) em Zig — Referência e Exemplos"
url: "https://ziglang.com.br/stdlib/std.io-buffered-bufferedreader/bufferedwriter-em-zig-refer%C3%AAncia-e-exemplos/"
markdown_url: "https://ziglang.com.br/stdlib/std.io-buffered-bufferedreader/bufferedwriter-em-zig-refer%C3%AAncia-e-exemplos.MD"
description: "Referência do BufferedReader e BufferedWriter em Zig. Aprenda a usar I/O com buffer para melhorar desempenho de leitura e escrita."
date: "2026-02-21"
author: "Zig Brasil"
---

# std.io Buffered (BufferedReader/BufferedWriter) em Zig — Referência e Exemplos

Referência do BufferedReader e BufferedWriter em Zig. Aprenda a usar I/O com buffer para melhorar desempenho de leitura e escrita.


# std.io Buffered — BufferedReader e BufferedWriter

Os tipos `BufferedReader` e `BufferedWriter` envolvem readers e writers existentes adicionando uma camada de buffering. Isso melhora significativamente o desempenho ao reduzir o número de syscalls para o sistema operacional, especialmente quando se faz muitas leituras ou escritas pequenas.

## Visão Geral

Sem buffering, cada chamada a `read()` ou `write()` resulta diretamente em uma syscall ao SO. Com buffering, as operações acumulam dados em um buffer intermediário em memória do usuário, fazendo syscalls apenas quando o buffer está cheio (escrita) ou vazio (leitura).

```zig
const std = @import("std");

// Funções de conveniência para criar readers/writers com buffer
const buf_reader = std.io.bufferedReader(reader_original);
const buf_writer = std.io.bufferedWriter(writer_original);
```

## Tipos Principais

### `BufferedReader`

```zig
pub fn BufferedReader(comptime ReaderType: type) type
```

O tipo retornado por `std.io.bufferedReader()`. O tamanho padrão do buffer é 4096 bytes.

**Métodos:**

```zig
// Obtém o reader com buffer
pub fn reader(self: *Self) Reader

// Acessa o reader subjacente
pub fn unbuffered(self: *Self) ReaderType
```

### `BufferedWriter`

```zig
pub fn BufferedWriter(comptime WriterType: type) type
```

O tipo retornado por `std.io.bufferedWriter()`. O tamanho padrão do buffer é 4096 bytes.

**Métodos:**

```zig
// Obtém o writer com buffer
pub fn writer(self: *Self) Writer

// Força a escrita de todos os dados pendentes no buffer
pub fn flush(self: *Self) !void

// Acessa o writer subjacente
pub fn unbuffered(self: *Self) WriterType
```

### Versões com Tamanho Customizado

```zig
// Reader com buffer de tamanho customizado
pub fn BufferedReaderSize(comptime ReaderType: type, comptime N: usize) type

// Writer com buffer de tamanho customizado
pub fn BufferedWriterSize(comptime WriterType: type, comptime N: usize) type

// Funções de conveniência
pub fn bufferedReaderSize(comptime N: usize, reader: anytype) BufferedReaderSize(@TypeOf(reader), N)
pub fn bufferedWriterSize(comptime N: usize, writer: anytype) BufferedWriterSize(@TypeOf(writer), N)
```

## Exemplo 1: Leitura Eficiente de Arquivo

Lendo um arquivo grande linha por linha com buffering:

```zig
const std = @import("std");

pub fn main() !void {
    const arquivo = try std.fs.cwd().openFile("log_grande.txt", .{});
    defer arquivo.close();

    // Envolver o reader do arquivo com um buffer de 4096 bytes
    var buf_reader = std.io.bufferedReader(arquivo.reader());
    const reader = buf_reader.reader();

    var contagem: usize = 0;
    var contagem_erros: usize = 0;
    var buf: [8192]u8 = undefined;

    while (reader.readUntilDelimiterOrEof(&buf, '\n')) |maybe_linha| {
        if (maybe_linha) |linha| {
            contagem += 1;
            if (std.mem.indexOf(u8, linha, "ERROR")) |_| {
                contagem_erros += 1;
            }
        } else break;
    } else |_| {}

    std.debug.print("Linhas totais: {d}\n", .{contagem});
    std.debug.print("Linhas com erro: {d}\n", .{contagem_erros});
}
```

## Exemplo 2: Escrita Eficiente com BufferedWriter

Gerando um arquivo CSV grande com buffering:

```zig
const std = @import("std");

pub fn main() !void {
    const arquivo = try std.fs.cwd().createFile("saida.csv", .{});
    defer arquivo.close();

    // Criar writer com buffer
    var buf_writer = std.io.bufferedWriter(arquivo.writer());
    const writer = buf_writer.writer();

    // Cabeçalho
    try writer.writeAll("id,nome,valor\n");

    // Gerar 10000 linhas — o buffer reduz as syscalls de escrita
    for (0..10000) |i| {
        try writer.print("{d},item_{d},{d:.2}\n", .{
            i,
            i,
            @as(f64, @floatFromInt(i)) * 1.5,
        });
    }

    // IMPORTANTE: sempre fazer flush ao terminar!
    try buf_writer.flush();

    std.debug.print("Arquivo CSV gerado com sucesso.\n", .{});
}
```

## Exemplo 3: Buffer de Tamanho Customizado

Para workloads específicos, ajustar o tamanho do buffer pode melhorar o desempenho:

```zig
const std = @import("std");

pub fn main() !void {
    const arquivo = try std.fs.cwd().openFile("dados_binarios.dat", .{});
    defer arquivo.close();

    // Buffer de 64 KB para leitura de dados grandes
    var buf_reader = std.io.bufferedReaderSize(64 * 1024, arquivo.reader());
    const reader = buf_reader.reader();

    // Ler dados em blocos
    var total_bytes: usize = 0;
    var temp_buf: [1024]u8 = undefined;

    while (true) {
        const n = try reader.read(&temp_buf);
        if (n == 0) break;
        total_bytes += n;
        // Processar temp_buf[0..n]...
    }

    std.debug.print("Total de bytes lidos: {d}\n", .{total_bytes});
}
```

## Padrões Comuns

### Padrão de Uso Típico

O padrão mais usado é criar o buffered reader/writer logo após abrir o arquivo:

```zig
const arquivo = try std.fs.cwd().openFile("dados.txt", .{});
defer arquivo.close();

// Para leitura
var br = std.io.bufferedReader(arquivo.reader());
const reader = br.reader();

// Para escrita
var bw = std.io.bufferedWriter(arquivo.writer());
const writer = bw.writer();
defer bw.flush() catch {};
```

### Sempre Fazer Flush

Ao usar `BufferedWriter`, dados podem permanecer no buffer após a última escrita. Sempre faça `flush()` antes de fechar o arquivo ou ao final da operação:

```zig
var bw = std.io.bufferedWriter(arquivo.writer());
const writer = bw.writer();

try writer.writeAll("dados importantes");
try bw.flush(); // Garante que tudo foi escrito no arquivo
```

### Combinando com Funções Genéricas

Funções que aceitam `anytype` funcionam transparentemente com writers/readers com buffer:

```zig
fn processar(reader: anytype, writer: anytype) !void {
    // Esta função funciona tanto com buffered quanto sem
    var buf: [1024]u8 = undefined;
    while (try reader.readUntilDelimiterOrEof(&buf, '\n')) |linha| {
        try writer.print(">> {s}\n", .{linha});
    }
}
```

### Escolhendo o Tamanho do Buffer

- **4096 bytes** (padrão): Bom para a maioria dos casos
- **8192-16384 bytes**: Para leitura/escrita de arquivos moderados
- **65536+ bytes**: Para processamento de arquivos grandes ou I/O de rede
- **Menor que 4096**: Raramente útil; apenas em situações com memória muito limitada

## Considerações de Desempenho

O ganho de desempenho com buffering é particularmente notável quando:

1. **Muitas operações pequenas**: Ler byte a byte ou escrever linhas curtas
2. **I/O de disco**: Reduz o número de syscalls `read()`/`write()`
3. **I/O de rede**: Reduz overhead de pacotes pequenos

Para leituras grandes e contíguas (ex: `readAll` de um bloco grande), o ganho é mínimo pois já há poucas syscalls.

## Módulos Relacionados

- [std.io](/stdlib/std-io/) — Visão geral do módulo de I/O
- [std.io.Writer](/stdlib/std-io-writer/) — Interface Writer
- [std.io.Reader](/stdlib/std-io-reader/) — Interface Reader
- [std.io.FixedBufferStream](/stdlib/std-io-fixed-buffer-stream/) — Stream sobre buffer em memória
- [std.fs.File](/stdlib/std-fs-file/) — Tipo File

## Tutoriais e Receitas Relacionados

- [Tutorial: Otimizando I/O em Zig](/tutoriais/otimizando-io/)
- [Receita: Processamento de Arquivos Grandes](/receitas/processamento-arquivos-grandes/)
- [Tutorial: Leitura e Escrita de Arquivos](/tutoriais/leitura-escrita-arquivos/)
