Introdução
Arquivos temporários são essenciais para armazenar dados intermediários durante processamento, testes e operações que precisam de espaço temporário em disco. Zig permite criar arquivos e diretórios temporários de forma segura, com controle explícito sobre a limpeza.
Nesta receita, você aprenderá a criar, usar e limpar arquivos e diretórios temporários.
Pré-requisitos
- Zig instalado (versão 0.13+). Veja o guia de instalação
- Conhecimento básico de Zig. Consulte a introdução ao Zig
Criar e Escrever em Arquivo Temporário
const std = @import("std");
pub fn main() !void {
// Obter diretório temporário do sistema
const tmp_dir = std.fs.cwd();
// Criar arquivo temporário
const tmp_file = try tmp_dir.createFile("temp_dados.tmp", .{});
defer {
tmp_file.close();
// Limpar: deletar o arquivo temporário
tmp_dir.deleteFile("temp_dados.tmp") catch {};
}
// Escrever dados
const writer = tmp_file.writer();
try writer.writeAll("Dados temporários linha 1\n");
try writer.writeAll("Dados temporários linha 2\n");
try writer.print("Timestamp: {d}\n", .{std.time.timestamp()});
std.debug.print("Arquivo temporário criado e escrito com sucesso\n", .{});
// Voltar ao início para ler
try tmp_file.seekTo(0);
// Ler de volta
var buf: [256]u8 = undefined;
const bytes = try tmp_file.readAll(&buf);
std.debug.print("Conteúdo ({d} bytes):\n{s}\n", .{ bytes, buf[0..bytes] });
}
Usar Diretório Temporário do Sistema
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Obter path do diretório temporário
const tmp_path = try std.fs.selfExeDirPathAlloc(allocator);
defer allocator.free(tmp_path);
std.debug.print("Diretório do executável: {s}\n", .{tmp_path});
// Usar /tmp diretamente (Linux)
const tmp = try std.fs.openDirAbsolute("/tmp", .{});
// Criar um arquivo com nome único
const pid = std.os.linux.getpid();
const nome = try std.fmt.allocPrint(allocator, "zig_temp_{d}.txt", .{pid});
defer allocator.free(nome);
const arquivo = try tmp.createFile(nome, .{});
defer {
arquivo.close();
tmp.deleteFile(nome) catch {};
}
try arquivo.writer().print("Arquivo temporário do processo {d}\n", .{pid});
std.debug.print("Criado /tmp/{s}\n", .{nome});
}
Criar Diretório Temporário
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const nome_dir = "zig_temp_dir";
// Criar diretório temporário
const cwd = std.fs.cwd();
cwd.makeDir(nome_dir) catch |err| {
if (err != error.PathAlreadyExists) return err;
};
defer {
// Limpar diretório e conteúdo
cwd.deleteTree(nome_dir) catch |err| {
std.debug.print("Erro ao limpar: {}\n", .{err});
};
}
// Abrir o diretório
var dir = try cwd.openDir(nome_dir, .{});
defer dir.close();
// Criar arquivos dentro do diretório temporário
for (0..3) |i| {
const nome = try std.fmt.allocPrint(allocator, "dados_{d}.txt", .{i});
defer allocator.free(nome);
const arquivo = try dir.createFile(nome, .{});
defer arquivo.close();
try arquivo.writer().print("Arquivo {d}\n", .{i});
std.debug.print("Criado {s}/{s}\n", .{ nome_dir, nome });
}
// Listar conteúdo
std.debug.print("\nConteúdo do diretório temporário:\n", .{});
var iter = dir.iterate();
while (try iter.next()) |entry| {
std.debug.print(" {s} ({s})\n", .{ entry.name, @tagName(entry.kind) });
}
}
Padrão: Processamento com Arquivo Temporário
Escrever resultado em arquivo temporário, depois renomear para destino final (atômico):
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const destino = "resultado_final.txt";
const tmp_nome = "resultado_final.txt.tmp";
const cwd = std.fs.cwd();
// Escrever em arquivo temporário
{
const tmp = try cwd.createFile(tmp_nome, .{});
defer tmp.close();
const writer = tmp.writer();
// Processar e escrever dados
for (0..10) |i| {
const linha = try std.fmt.allocPrint(allocator, "Resultado {d}: {d}\n", .{ i, i * i });
defer allocator.free(linha);
try writer.writeAll(linha);
}
}
// Renomear atomicamente (garante integridade)
cwd.rename(tmp_nome, destino) catch |err| {
std.debug.print("Erro ao renomear: {}\n", .{err});
// Limpar arquivo temporário em caso de falha
cwd.deleteFile(tmp_nome) catch {};
return err;
};
std.debug.print("Arquivo '{s}' criado com sucesso\n", .{destino});
// Verificar resultado
const conteudo = try cwd.readFileAlloc(allocator, destino, 4096);
defer allocator.free(conteudo);
std.debug.print("Conteúdo:\n{s}", .{conteudo});
// Limpar
try cwd.deleteFile(destino);
}
Dicas e Boas Práticas
Sempre limpe arquivos temporários: Use
deferpara garantir que arquivos e diretórios temporários sejam removidos.Nomes únicos: Use PID, timestamp ou UUID para evitar conflitos entre processos.
Escrita atômica: Escreva em arquivo temporário e renomeie para o destino final para evitar corrupção.
deleteTreepara diretórios: Remove diretório e todo seu conteúdo recursivamente.Permissões: Arquivos em
/tmpsão acessíveis por outros processos. Use permissões restritivas para dados sensíveis.
Receitas Relacionadas
- Ler Conteúdo de Arquivo - Ler arquivos
- Escrever em Arquivo - Escrever arquivos
- Criar Diretórios - Criar diretórios
- Manipulação de Caminhos - Trabalhar com paths