Como Escrever em Arquivo em Zig

Como Escrever em Arquivo em Zig

Escrever em arquivos é essencial para persistência de dados, geração de relatórios e logs. Zig oferece uma API direta para criação e escrita de arquivos com controle preciso sobre o comportamento de criação.

Criar e Escrever Arquivo Novo

Use createFile para criar um arquivo novo ou sobrescrever um existente.

const std = @import("std");

pub fn main() !void {
    // Criar arquivo (sobrescreve se existir)
    const arquivo = try std.fs.cwd().createFile("saida.txt", .{});
    defer arquivo.close();

    // Escrever conteúdo
    try arquivo.writeAll("Olá, Mundo!\n");
    try arquivo.writeAll("Esta é a segunda linha.\n");
    try arquivo.writeAll("Escrito com Zig.\n");

    const stdout = std.io.getStdOut().writer();
    try stdout.print("Arquivo 'saida.txt' criado com sucesso!\n", .{});
}

Escrever com Formatação

Use o writer do arquivo para escrever dados formatados diretamente.

const std = @import("std");

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

    const writer = arquivo.writer();

    // Escrever com formatação
    try writer.print("Relatório de Vendas\n", .{});
    try writer.print("{s}\n", .{"=" ** 30});
    try writer.print("Data: {d:0>2}/{d:0>2}/{d}\n", .{ @as(u32, 21), @as(u32, 2), @as(u32, 2026) });
    try writer.print("\n", .{});

    // Tabela formatada
    const produtos = [_]struct { nome: []const u8, qtd: u32, preco: f64 }{
        .{ .nome = "Teclado", .qtd = 15, .preco = 199.90 },
        .{ .nome = "Mouse", .qtd = 30, .preco = 89.90 },
        .{ .nome = "Monitor", .qtd = 5, .preco = 1299.00 },
    };

    try writer.print("{s:<15} {s:>5} {s:>12}\n", .{ "Produto", "Qtd", "Preço" });
    try writer.print("{s}\n", .{"-" ** 35});

    var total: f64 = 0;
    for (produtos) |p| {
        const subtotal = @as(f64, @floatFromInt(p.qtd)) * p.preco;
        try writer.print("{s:<15} {d:>5} R$ {d:>8.2}\n", .{ p.nome, p.qtd, p.preco });
        total += subtotal;
    }
    try writer.print("{s}\n", .{"-" ** 35});
    try writer.print("Total: R$ {d:.2}\n", .{total});

    const stdout = std.io.getStdOut().writer();
    try stdout.print("Relatório gerado em 'relatorio.txt'\n", .{});
}

Adicionar ao Final (Append)

Para adicionar conteúdo ao final de um arquivo existente sem sobrescrevê-lo.

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    // Abrir arquivo para append
    const arquivo = std.fs.cwd().openFile("log.txt", .{ .mode = .write_only }) catch |err| blk: {
        if (err == error.FileNotFound) {
            // Se não existir, criar novo
            break :blk try std.fs.cwd().createFile("log.txt", .{});
        }
        return err;
    };
    defer arquivo.close();

    // Mover cursor para o final
    try arquivo.seekFromEnd(0);

    const writer = arquivo.writer();

    // Adicionar entrada de log
    try writer.print("[INFO] Aplicação iniciada\n", .{});
    try writer.print("[INFO] Conexão estabelecida\n", .{});

    try stdout.print("Log atualizado com sucesso!\n", .{});
}

Escrever Bytes e Dados Binários

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    const arquivo = try std.fs.cwd().createFile("dados.bin", .{});
    defer arquivo.close();

    // Escrever bytes individuais
    const header = [_]u8{ 0x89, 0x50, 0x4E, 0x47 }; // exemplo: magic bytes
    try arquivo.writeAll(&header);

    // Escrever inteiros em formato little-endian
    const writer = arquivo.writer();
    try writer.writeInt(u32, 12345, .little);
    try writer.writeInt(u16, 42, .little);

    // Escrever struct como bytes
    const Registro = extern struct {
        id: u32,
        valor: f32,
        ativo: u8,
    };

    const reg = Registro{ .id = 1, .valor = 3.14, .ativo = 1 };
    try arquivo.writeAll(std.mem.asBytes(&reg));

    try stdout.print("Dados binários escritos com sucesso!\n", .{});
}

Escrever Arquivo com Buffered Writer

Para melhor desempenho em escritas frequentes, use um BufferedWriter.

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    const arquivo = try std.fs.cwd().createFile("grande.txt", .{});
    defer arquivo.close();

    // Criar buffered writer para melhor desempenho
    var buf_writer = std.io.bufferedWriter(arquivo.writer());
    const writer = buf_writer.writer();

    // Escrever muitas linhas
    for (0..1000) |i| {
        try writer.print("Linha {d:0>4}: Este é um exemplo de texto repetido.\n", .{i + 1});
    }

    // Garantir que tudo foi escrito (flush do buffer)
    try buf_writer.flush();

    try stdout.print("Arquivo com 1000 linhas criado!\n", .{});
}

Escrever com Caminho Absoluto

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    // Criar arquivo em caminho absoluto
    const arquivo = try std.fs.createFileAbsolute("/tmp/teste_zig.txt", .{});
    defer arquivo.close();

    try arquivo.writeAll("Arquivo temporário criado por Zig\n");
    try stdout.print("Arquivo criado em /tmp/teste_zig.txt\n", .{});
}

Exemplo Prático: Exportar CSV

const std = @import("std");

const Aluno = struct {
    nome: []const u8,
    nota1: f64,
    nota2: f64,
    nota3: f64,

    fn media(self: Aluno) f64 {
        return (self.nota1 + self.nota2 + self.nota3) / 3.0;
    }
};

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    const alunos = [_]Aluno{
        .{ .nome = "Ana Silva", .nota1 = 8.5, .nota2 = 9.0, .nota3 = 7.5 },
        .{ .nome = "Carlos Souza", .nota1 = 6.0, .nota2 = 7.0, .nota3 = 8.0 },
        .{ .nome = "Maria Santos", .nota1 = 9.5, .nota2 = 10.0, .nota3 = 9.0 },
        .{ .nome = "João Lima", .nota1 = 5.0, .nota2 = 6.5, .nota3 = 7.0 },
    };

    const arquivo = try std.fs.cwd().createFile("notas.csv", .{});
    defer arquivo.close();

    var buf_writer = std.io.bufferedWriter(arquivo.writer());
    const writer = buf_writer.writer();

    // Cabeçalho CSV
    try writer.print("Nome,Nota1,Nota2,Nota3,Média,Situação\n", .{});

    // Dados
    for (alunos) |aluno| {
        const media = aluno.media();
        const situacao = if (media >= 7.0) "Aprovado" else "Reprovado";
        try writer.print("{s},{d:.1},{d:.1},{d:.1},{d:.1},{s}\n", .{
            aluno.nome, aluno.nota1, aluno.nota2, aluno.nota3, media, situacao,
        });
    }

    try buf_writer.flush();
    try stdout.print("Arquivo 'notas.csv' exportado com {d} registros\n", .{alunos.len});
}

Veja Também

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.