---
title: "std.io.Reader em Zig — Referência e Exemplos"
url: "https://ziglang.com.br/stdlib/std.io.reader-em-zig-refer%C3%AAncia-e-exemplos/"
markdown_url: "https://ziglang.com.br/stdlib/std.io.reader-em-zig-refer%C3%AAncia-e-exemplos.MD"
description: "Referência completa da interface Reader do std.io em Zig. Métodos de leitura, leitura linha por linha e padrões práticos em português."
date: "2026-02-21"
author: "Zig Brasil"
---

# std.io.Reader em Zig — Referência e Exemplos

Referência completa da interface Reader do std.io em Zig. Métodos de leitura, leitura linha por linha e padrões práticos em português.


# std.io.Reader — Interface de Leitura

A interface `Reader` é o mecanismo genérico do Zig para leitura de bytes. Assim como o `Writer`, ela é parametrizada em tempo de compilação, permitindo que o mesmo código funcione com arquivos, sockets, buffers em memória e qualquer outro tipo que forneça uma função de leitura.

## Visão Geral

O `Reader` é definido pelo tipo parametrizado `GenericReader`:

```zig
pub fn GenericReader(
    comptime Context: type,
    comptime ReadError: type,
    comptime readFn: fn (Context, []u8) ReadError!usize,
) type
```

A função `readFn` deve:
- Preencher o buffer fornecido com dados lidos
- Retornar o número de bytes efetivamente lidos
- Retornar 0 para indicar fim do fluxo (EOF)

## Métodos Principais

### Leitura Básica

```zig
// Lê bytes para o buffer; retorna quantos foram lidos (0 = EOF)
pub fn read(self: Self, buffer: []u8) ReadError!usize

// Lê exatamente buffer.len bytes ou retorna erro
pub fn readAll(self: Self, buffer: []u8) ReadError!usize

// Lê exatamente N bytes; retorna erro se não conseguir
pub fn readNoEof(self: Self, buf: *[N]u8) (ReadError || error{EndOfStream})!void

// Lê um único byte
pub fn readByte(self: Self) (ReadError || error{EndOfStream})!u8
```

### Leitura por Delimitador

```zig
// Lê até encontrar o delimitador ou EOF
pub fn readUntilDelimiterOrEof(
    self: Self,
    buf: []u8,
    delimiter: u8,
) (ReadError || error{StreamTooLong})!?[]u8

// Lê até o delimitador, alocando memória conforme necessário
pub fn readUntilDelimiterAlloc(
    self: Self,
    allocator: std.mem.Allocator,
    delimiter: u8,
    max_size: usize,
) (ReadError || error{StreamTooLong} || Allocator.Error)![]u8
```

### Leitura de Tipos

```zig
// Lê um inteiro com endianness especificado
pub fn readInt(self: Self, comptime T: type, endian: std.builtin.Endian) !T

// Lê uma struct empacotada (packed)
pub fn readStruct(self: Self, comptime T: type) !T
```

### Controle de Fluxo

```zig
// Descarta N bytes do fluxo
pub fn skipBytes(self: Self, num_bytes: u64, options: SkipBytesOptions) !void

// Lê e descarta todos os bytes restantes
pub fn discard(self: Self) !u64

// Verifica se o reader ainda tem dados
pub fn any(self: Self) bool
```

## Exemplo 1: Leitura Linha por Linha

O caso de uso mais comum é ler um fluxo linha por linha:

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

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

    var buf_reader = std.io.bufferedReader(arquivo.reader());
    const reader = buf_reader.reader();

    var buf: [4096]u8 = undefined;
    var num_linha: usize = 0;

    while (reader.readUntilDelimiterOrEof(&buf, '\n')) |maybe_linha| {
        if (maybe_linha) |linha| {
            num_linha += 1;
            std.debug.print("{d:>4}: {s}\n", .{ num_linha, linha });
        } else {
            break; // EOF
        }
    } else |err| {
        std.debug.print("Erro na leitura: {}\n", .{err});
    }

    std.debug.print("\nTotal: {d} linhas\n", .{num_linha});
}
```

## Exemplo 2: Leitura da Entrada Padrão com Alocação

Usando `readUntilDelimiterAlloc` para linhas de tamanho variável:

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

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const stdin = std.io.getStdIn().reader();
    const stdout = std.io.getStdOut().writer();

    try stdout.writeAll("Digite palavras (uma por linha, 'sair' para encerrar):\n");

    var palavras = std.ArrayList([]const u8).init(allocator);
    defer {
        for (palavras.items) |p| allocator.free(p);
        palavras.deinit();
    }

    while (true) {
        try stdout.writeAll("> ");
        const linha = stdin.readUntilDelimiterAlloc(
            allocator,
            '\n',
            1024 * 1024, // máximo 1 MB por linha
        ) catch |err| {
            std.debug.print("Erro: {}\n", .{err});
            break;
        };

        if (std.mem.eql(u8, linha, "sair")) {
            allocator.free(linha);
            break;
        }

        try palavras.append(linha);
    }

    try stdout.print("\nVocê digitou {d} palavras:\n", .{palavras.items.len});
    for (palavras.items, 0..) |palavra, i| {
        try stdout.print("  {d}. {s}\n", .{ i + 1, palavra });
    }
}
```

## Exemplo 3: Leitura de Dados Binários

Lendo um formato binário simples (cabeçalho + dados):

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

const Cabecalho = packed struct {
    magic: u32,
    versao: u16,
    num_registros: u16,
};

fn lerDadosBinarios(reader: anytype) !void {
    // Ler cabeçalho
    const cabecalho = try reader.readStruct(Cabecalho);

    if (cabecalho.magic != 0x5A494742) { // "ZIGB"
        return error.FormatoInvalido;
    }

    std.debug.print("Versão: {d}, Registros: {d}\n", .{
        cabecalho.versao,
        cabecalho.num_registros,
    });

    // Ler cada registro (inteiros de 32 bits)
    for (0..cabecalho.num_registros) |i| {
        const valor = try reader.readInt(u32, .little);
        std.debug.print("  Registro {d}: {d}\n", .{ i, valor });
    }
}

pub fn main() !void {
    const arquivo = try std.fs.cwd().openFile("dados.bin", .{});
    defer arquivo.close();
    try lerDadosBinarios(arquivo.reader());
}
```

## Padrões Comuns

### Leitura Completa para Memória

Para ler um arquivo inteiro de uma vez:

```zig
const conteudo = try std.fs.cwd().readFileAlloc(allocator, "config.txt", 1024 * 1024);
defer allocator.free(conteudo);
```

### Iteração com readUntilDelimiterOrEof

O padrão idiomático para processar todas as linhas:

```zig
var buf: [4096]u8 = undefined;
while (try reader.readUntilDelimiterOrEof(&buf, '\n')) |linha| {
    // processar `linha`
}
// Chegou ao EOF
```

### Combinando Reader com BufferedReader

Sempre que ler de um arquivo ou socket, use buffering para melhor desempenho:

```zig
var buffered = std.io.bufferedReader(fonte.reader());
const reader = buffered.reader();
```

## Erros Comuns

- **`error.EndOfStream`**: Tentou ler mais bytes do que os disponíveis com `readNoEof`
- **`error.StreamTooLong`**: A linha/token excedeu o tamanho do buffer fornecido

## 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 complementar de escrita
- [std.io Buffered](/stdlib/std-io-buffered/) — Reader com buffering
- [std.io.FixedBufferStream](/stdlib/std-io-fixed-buffer-stream/) — Reader/Writer sobre buffer fixo
- [std.fs.File](/stdlib/std-fs-file/) — Tipo File que implementa Reader

## Tutoriais e Receitas Relacionados

- [Tutorial: Leitura de Arquivos em Zig](/tutoriais/leitura-escrita-arquivos/)
- [Receita: Processamento de Texto Linha por Linha](/receitas/processamento-texto-linha/)
- [Receita: Parsing de Dados Binários](/receitas/parsing-binario/)
