Saltar al contenido principal

E/S de Archivos

Leer y escribir archivos es una operación fundamental. Así es como los diferentes lenguajes manejan las operaciones de archivos.

Lectura de Archivos​

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);
}

Escritura de Archivos​

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();

Puntos Clave​

  • APIs síncronas y asíncronas coexisten — La mayoría de los lenguajes ofrecen ambas: Node.js tiene fs.readFileSync y fs.promises.readFile; C# tiene File.ReadAllText y File.ReadAllTextAsync; el open() de Python es síncrono por defecto, aunque asyncio puede envolverlo. Para cargas de trabajo con mucha E/S (por ejemplo, servidores web leyendo muchos archivos), prefiere async para evitar bloqueos; para scripts o herramientas CLI, sync suele ser más simple. Elige un lenguaje que soporte tu modelo de concurrencia—Node.js y C# son async-first; Rust ofrece tokio para E/S de archivos asíncrona.

  • Los patrones de limpieza de recursos difieren — El with open('file.txt') as f: de Python y el using/try-with-resources de C#/Java, más el RAII de Rust, garantizan el cierre incluso ante errores. Go usa defer file.Close() que se ejecuta cuando la función retorna. C y Zig requieren fclose o file.close() explícito—si ocurre un error antes del cierre, el handle puede fugarse. Prefiere patrones basados en bloques o RAII cuando estén disponibles; en C o Zig, estructura el código para que cada open tenga un close correspondiente en la misma ruta de control.

  • El manejo de codificación es explícito en algunos lenguajes — Python y Node.js aceptan encoding='utf-8' al leer texto; C# usa UTF-8 por defecto en APIs más nuevas. C y C++ tratan los archivos como bytes crudos; debes usar bibliotecas o conversión manual para UTF-8. Zig expone APIs de bytes de bajo nivel—readFileAlloc retorna []u8, y tú manejas la decodificación de strings. Para texto internacional, prefiere Python, C# o Java; para binario o cuando necesitas control total, C/C++/Zig son apropiados.

  • Helpers de alto nivel vs control manual — C#, Python y Java ofrecen File.ReadAllText, Path('file.txt').read_text() y Files.readString(Path.of("file.txt")) para lecturas en una línea. C y Zig requieren asignación manual de buffers, bucles fread/read y terminación nula. Las APIs de alto nivel son convenientes pero pueden cargar archivos completos en memoria; para archivos grandes, usa streaming (por ejemplo, File.ReadLines, BufferedReader o BufReader de Rust). Elige helpers para archivos pequeños; usa streams cuando la memoria o la latencia importen.

  • Las APIs basadas en bloques evitan fugas — El File.open('file.txt') { |f| } de Ruby y el with open('file.txt') as f: de Python garantizan el cierre incluso cuando ocurren excepciones. El fclose explícito en C y PHP puede causar fugas si ocurre un error antes del cierre—por ejemplo, un return o throw en medio del procesamiento. Siempre prefiere patrones basados en bloques o RAII cuando estén disponibles; en C, considera usar goto a una etiqueta de limpieza o un patrón de wrapper mínimo para centralizar la lógica de cierre.