std.fs.File — Tipo File e Operações
O tipo std.fs.File representa um descritor de arquivo aberto no sistema operacional. Ele fornece métodos para leitura, escrita, posicionamento, obtenção de metadados e conversão para as interfaces genéricas Reader e Writer.
Visão Geral
Um File é obtido através de operações em Dir (como openFile ou createFile) ou pelas funções getStdOut(), getStdErr() e getStdIn().
const std = @import("std");
const arquivo = try std.fs.cwd().openFile("dados.txt", .{});
defer arquivo.close();
Campos e Tipos
OpenFlags
pub const OpenFlags = struct {
mode: enum { read_only, read_write, write_only } = .read_only,
lock: Lock = .none,
};
CreateFlags
pub const CreateFlags = struct {
read: bool = false,
truncate: bool = true,
exclusive: bool = false,
lock: Lock = .none,
mode: u32 = 0o666, // Permissões Unix
};
Stat
pub const Stat = struct {
inode: u64,
size: u64,
mtime: i128, // Tempo de modificação em nanosegundos
atime: i128, // Tempo de acesso
ctime: i128, // Tempo de mudança de status
mode: u32,
};
Métodos Principais
Leitura e Escrita
// Ler para buffer; retorna bytes lidos
pub fn read(self: File, buffer: []u8) ReadError!usize
// Ler exatamente buffer.len bytes
pub fn readAll(self: File, buffer: []u8) ReadError!usize
// Escrever bytes; retorna bytes escritos
pub fn write(self: File, bytes: []const u8) WriteError!usize
// Escrever todos os bytes
pub fn writeAll(self: File, bytes: []const u8) WriteError!void
// Obter reader genérico
pub fn reader(self: File) Reader
// Obter writer genérico
pub fn writer(self: File) Writer
Posicionamento
// Mover cursor para posição absoluta
pub fn seekTo(self: File, pos: u64) SeekError!void
// Mover cursor relativamente
pub fn seekBy(self: File, amt: i64) SeekError!void
// Obter posição atual
pub fn getPos(self: File) GetSeekPosError!u64
// Obter tamanho do arquivo
pub fn getEndPos(self: File) GetSeekPosError!u64
Metadados
// Obter estatísticas do arquivo
pub fn stat(self: File) StatError!Stat
// Definir o tamanho do arquivo
pub fn setEndPos(self: File, length: u64) !void
Controle
// Fechar o arquivo
pub fn close(self: File) void
// Sincronizar dados com disco
pub fn sync(self: File) SyncError!void
// Verifica suporte a escape ANSI
pub fn supportsAnsiEscapeCodes(self: File) bool
Exemplo 1: Leitura e Escrita Completas
const std = @import("std");
pub fn main() !void {
const cwd = std.fs.cwd();
// Criar arquivo e escrever dados
{
const arquivo = try cwd.createFile("dados.bin", .{});
defer arquivo.close();
// Escrever cabeçalho
try arquivo.writeAll("ZIGF"); // magic bytes
// Escrever números em formato binário
const writer = arquivo.writer();
try writer.writeInt(u32, 42, .little);
try writer.writeInt(u32, 100, .little);
try writer.writeInt(u32, 255, .little);
const stat = try arquivo.stat();
std.debug.print("Arquivo criado: {d} bytes\n", .{stat.size});
}
// Ler o arquivo
{
const arquivo = try cwd.openFile("dados.bin", .{});
defer arquivo.close();
// Ler magic bytes
var magic: [4]u8 = undefined;
_ = try arquivo.readAll(&magic);
std.debug.print("Magic: {s}\n", .{&magic});
// Ler números
const reader = arquivo.reader();
for (0..3) |i| {
const valor = try reader.readInt(u32, .little);
std.debug.print("Valor {d}: {d}\n", .{ i, valor });
}
}
try cwd.deleteFile("dados.bin");
}
Exemplo 2: Posicionamento no Arquivo
const std = @import("std");
pub fn main() !void {
const cwd = std.fs.cwd();
const arquivo = try cwd.createFile("posicao.txt", .{ .read = true });
defer arquivo.close();
defer cwd.deleteFile("posicao.txt") catch {};
// Escrever dados
try arquivo.writeAll("ABCDEFGHIJ0123456789");
// Voltar ao início
try arquivo.seekTo(0);
// Ler os primeiros 5 bytes
var buf: [5]u8 = undefined;
_ = try arquivo.readAll(&buf);
std.debug.print("Posição 0-4: {s}\n", .{&buf}); // ABCDE
// Pular para posição 10
try arquivo.seekTo(10);
_ = try arquivo.readAll(&buf);
std.debug.print("Posição 10-14: {s}\n", .{&buf}); // 01234
// Posição atual
const pos = try arquivo.getPos();
std.debug.print("Posição atual: {d}\n", .{pos}); // 15
// Tamanho total
const tamanho = try arquivo.getEndPos();
std.debug.print("Tamanho total: {d}\n", .{tamanho}); // 20
}
Exemplo 3: Copiando Arquivos
const std = @import("std");
fn copiarArquivo(cwd: std.fs.Dir, origem: []const u8, destino: []const u8) !void {
const src = try cwd.openFile(origem, .{});
defer src.close();
const dst = try cwd.createFile(destino, .{});
defer dst.close();
var buf: [4096]u8 = undefined;
var total: usize = 0;
while (true) {
const n = try src.read(&buf);
if (n == 0) break;
try dst.writeAll(buf[0..n]);
total += n;
}
std.debug.print("Copiados {d} bytes: {s} -> {s}\n", .{ total, origem, destino });
}
pub fn main() !void {
const cwd = std.fs.cwd();
// Criar arquivo de teste
{
const f = try cwd.createFile("original.txt", .{});
defer f.close();
try f.writeAll("Conteúdo do arquivo original.\nSegunda linha.\n");
}
try copiarArquivo(cwd, "original.txt", "copia.txt");
// Verificar a cópia
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const conteudo = try cwd.readFileAlloc(gpa.allocator(), "copia.txt", 1024 * 1024);
defer gpa.allocator().free(conteudo);
std.debug.print("Conteúdo da cópia:\n{s}", .{conteudo});
// Limpar
try cwd.deleteFile("original.txt");
try cwd.deleteFile("copia.txt");
}
Padrões Comuns
Sempre Usar defer para Fechar
const arquivo = try std.fs.cwd().openFile("dados.txt", .{});
defer arquivo.close();
Leitura com Buffering
Para muitas leituras pequenas, use BufferedReader:
const arquivo = try cwd.openFile("log.txt", .{});
defer arquivo.close();
var br = std.io.bufferedReader(arquivo.reader());
const reader = br.reader();
Escrita Atômica
const tmp = try cwd.createFile("dados.tmp", .{});
defer tmp.close();
try tmp.writeAll(conteudo);
try tmp.sync(); // Garantir que dados estão no disco
tmp.close();
try cwd.rename("dados.tmp", "dados.txt");
Módulos Relacionados
- std.fs — Visão geral do sistema de arquivos
- std.fs.cwd() — Diretório de trabalho atual
- std.fs.Dir — Tipo Dir e iteração
- std.io.Writer — Interface Writer
- std.io.Reader — Interface Reader