Pular para o conteúdo principal

I/O de Arquivos

Ler e escrever arquivos é uma operação fundamental. Veja como diferentes linguagens lidam com operações de arquivo.

Lendo Arquivos​

const fs = require('fs');
const fsPromises = require('fs/promises');

// Synchronous
const data = fs.readFileSync('file.txt', 'utf8');

// Asynchronous (callback)
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});

// Async/await (modern)
const data2 = await fsPromises.readFile('file.txt', 'utf8');

// Read line by line
const readline = require('readline');
const rl = readline.createInterface({
input: fs.createReadStream('file.txt'),
});
for await (const line of rl) {
console.log(line);
}

Escrevendo Arquivos​

const fs = require('fs');
const fsPromises = require('fs/promises');

// Write (overwrite)
fs.writeFileSync('output.txt', 'Hello World');

// Write async
await fsPromises.writeFile('output.txt', 'Hello World');

// Append
fs.appendFileSync('output.txt', '\nNew line');

// Write with stream
const stream = fs.createWriteStream('output.txt');
stream.write('Line 1\n');
stream.write('Line 2\n');
stream.end();

Principais Conclusões​

  • APIs síncronas vs assíncronas coexistem — A maioria das linguagens oferece ambas: Node.js tem fs.readFileSync e fs.promises.readFile; C# tem File.ReadAllText e File.ReadAllTextAsync; o open() do Python é síncrono por padrão, embora asyncio possa envolvê-lo. Para cargas de trabalho orientadas a I/O (ex.: servidores web lendo muitos arquivos), prefira assíncrono para evitar bloqueio; para scripts ou ferramentas CLI, síncrono geralmente é mais simples. Escolha uma linguagem que suporte seu modelo de concorrência — Node.js e C# são async-first; Rust oferece tokio para I/O de arquivo assíncrono.

  • Padrões de limpeza de recursos diferem — O with open('file.txt') as f: do Python e o using/try-with-resources do C#/Java, mais o RAII do Rust, garantem o fechamento mesmo em caso de erros. Go usa defer file.Close() que executa quando a função retorna. C e Zig exigem fclose ou file.close() explícitos — se um erro ocorrer antes do close, o handle pode vazar. Prefira padrões baseados em bloco ou RAII quando disponíveis; em C ou Zig, estruture o código para que todo open tenha um close correspondente no mesmo caminho de controle.

  • Tratamento de encoding é explícito em algumas linguagens — Python e Node.js aceitam encoding='utf-8' ao ler texto; C# usa UTF-8 por padrão em APIs mais recentes. C e C++ tratam arquivos como bytes brutos; você deve usar bibliotecas ou conversão manual para UTF-8. Zig expõe APIs de bytes de baixo nível — readFileAlloc retorna []u8, e você cuida da decodificação de string. Para texto internacional, prefira Python, C# ou Java; para binário ou quando precisar de controle total, C/C++/Zig são apropriados.

  • Helpers de alto nível vs controle manual — C#, Python e Java oferecem File.ReadAllText, Path('file.txt').read_text() e Files.readString(Path.of("file.txt")) para leituras em uma linha. C e Zig exigem alocação manual de buffer, loops fread/read e terminação nula. APIs de alto nível são convenientes mas podem carregar arquivos inteiros na memória; para arquivos grandes, use streaming (ex.: File.ReadLines, BufferedReader ou BufReader do Rust). Escolha helpers para arquivos pequenos; use streams quando memória ou latência importarem.

  • APIs baseadas em bloco evitam vazamentos — O File.open('file.txt') { |f| } do Ruby e o with open('file.txt') as f: do Python garantem o fechamento mesmo quando exceções ocorrem. fclose explícito em C e PHP pode levar a vazamentos se um erro acontecer antes do close — ex.: um return ou throw no meio do processamento. Sempre prefira padrões baseados em bloco ou RAII quando disponíveis; em C, considere usar goto para um label de limpeza ou um padrão de wrapper mínimo para centralizar a lógica de close.