Modo de abertura de arquivo em Ruby/Python e etc

Modo de abertura de arquivo em Ruby/Python e etc
Photo by Fahrul Razi / Unsplash

No momento que escrevo esse post estou ensinando os meus alunos a trabalhar com os arquivos e isso é muito legal, porque quando você compreende como funciona a abertura de arquivos e a manipulação desses dados pela linguagem alvo, você compreende a teoria da computação que tudo é uma string com diversos escaping que lhe permitirá converter para diversos tipos de arquivo, como csv, json, xml e etc, você vai escolher.

Vamos por parte, primeiro é importante compreendermos uma tabela com os modos de abertura e depois eu retorno código para você.

Modo Descrição Ruby Python Go C Java Node.js
r Abre o arquivo apenas para leitura. ✔️ ✔️ ✔️ ✔️ FileInputStream fs.openSync/readFileSync
w Abre o arquivo para escrita, truncando o arquivo existente. ✔️ ✔️ ✔️ ✔️ FileOutputStream fs.openSync/writeFileSync
a Abre o arquivo para escrita, adicionando ao final sem truncar. ✔️ ✔️ ✔️ ✔️ FileOutputStream (Append) fs.appendFileSync
r+ Abre o arquivo para leitura e escrita, sem truncar. ✔️ ✔️ ✔️ RandomAccessFile fs.openSync
w+ Abre o arquivo para leitura e escrita, truncando o existente. ✔️ ✔️ ✔️ RandomAccessFile fs.openSync
a+ Abre o arquivo para leitura e escrita, adicionando ao final. ✔️ ✔️ ✔️ RandomAccessFile fs.openSync

Diferenças e Particularidades

  • Ruby e Python:

    • Ambas as linguagens possuem suporte completo para os modos listados, utilizando bibliotecas padrão (csv em Ruby e open em Python).
    • Utilizam sintaxes e APIs similares para manipulação de arquivos, facilitando operações como leitura, escrita e anexação.
  • Go:

    • Não possui um equivalente direto para os modos r+, w+, a+ como operações únicas. Utiliza diferentes funções para abertura e manipulação de arquivos (os.Open, os.Create).
    • Foco em performance e segurança, com tratamento explícito de erros.
  • C:

    • Oferece funções como fopen, fread, fwrite com suporte aos modos via strings ("r", "w", "a" etc.).
    • Exige gerenciamento manual de recursos, como fechar arquivos explicitamente.
  • Java:

    • Não usa os mesmos modos de string; em vez disso, utiliza classes específicas como FileInputStream, FileOutputStream e RandomAccessFile para diferentes operações.
    • RandomAccessFile permite leitura e escrita com acesso direto, semelhante aos modos r+, w+, a+.
  • Node.js:

    • Utiliza funções do módulo fs como fs.openSync, fs.readFileSync para operações sincronizadas.
    • Modos como r+, w+, a+ são especificados como strings em chamadas de função.

Dito isso, você precisará sempre compreender o seu problema e o como irá solucionar-ló. Perceba que os modos dirá se seu arquivo será alterado, será truncado, truncado no contexto de arquivos, estamos dizendo que será removido todo o conteúdo do arquivo atual e será alterado para um dado novo.

Quer codificar um pouco comigo? jaja, vamos lá, em Ruby:

require 'csv'

def add_entry_to_large_csv(file_path, id, name, email)
  CSV.open(file_path, 'a') do |csv|
    csv << [id, name, email]
  end
end

# Exemplo de uso
file_path = 'large_data.csv'
add_entry_to_large_csv(file_path, "004", "Jane Doe", "[email protected]")

Lendo a nossa tabela, com o modo a, poderemos adicionar ao final da última linha e inserir um dado de maneira segura, sem truncar (remover) os dados anteriores.

Exemplo em python:

import csv

def add_entry_to_large_csv(file_path, id, name, email):
    with open(file_path, mode='a', newline='') as file:
        writer = csv.writer(file)
        writer.writerow([id, name, email])

# Exemplo de uso
file_path = 'large_data.csv'
add_entry_to_large_csv(file_path, "004", "Jane Doe", "[email protected]")

Exemplo em Go:

package main

import (
    "encoding/csv"
    "os"
)

func addEntryToLargeCSV(filePath, id, name, email string) {
    file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    if err != nil {
        panic(err)
    }
    defer file.Close()

    writer := csv.NewWriter(file)
    defer writer.Flush()

    if err := writer.Write([]string{id, name, email}); err != nil {
        panic(err)
    }
}

func main() {
    filePath := "large_data.csv"
    addEntryToLargeCSV(filePath, "004", "Jane Doe", "[email protected]")
}

Na linguagem Go especifica as permissões do arquivo e é baseado no sistema de permissões Unix. Essas permissões determinam quem pode ler, escrever ou executar o arquivo e são definidas usando um sistema de codificação octal. No código, onde você verifica: 0644, é a representação das permissões. Aqui está como as permissões são atribuídas e o que cada número representa:

Permissões no Sistema Unix

  • 0: Nenhuma permissão
  • 1: Permissão de execução
  • 2: Permissão de escrita
  • 4: Permissão de leitura

Em Node por exemplo:

const fs = require('fs');
const csvWriter = require('csv-write-stream');

function addEntryToLargeCSV(filePath, id, name, email) {
    const writer = csvWriter({ sendHeaders: false });
    writer.pipe(fs.createWriteStream(filePath, { flags: 'a' }));
    writer.write({ id, name, email });
    writer.end();
}

// Exemplo de uso
const filePath = 'large_data.csv';
addEntryToLargeCSV(filePath, "004", "Jane Doe", "[email protected]");


De modo geral, eu desejei mostrar que as linguagens sempre precisam dessa segurança e que elas fazem com que possamos criar regras de negócios que proteja nosso arquivo de ações indesejadas como excluir o conteúdo durante uma inserção.

Read more