Retour au cours

lecture et écriture de fichiers

Objectifs

  • Lire le contenu d’un fichier, soit en une seule fois, soit ligne par ligne.
  • Écrire du texte dans un fichier, en écrasant son contenu ou en y ajoutant des informations.
  • Utiliser la syntaxe avec un bloc pour une gestion plus sûre des fichiers.

Ruby fournit des méthodes simples et puissantes pour interagir avec le système de fichiers via la classe File.

Lire des fichiers

Lire un fichier d’un seul coup : File.read

C’est la méthode la plus simple, mais elle doit être utilisée avec prudence. Elle lit l’intégralité du contenu du fichier et le charge en mémoire dans une seule chaîne de caractères.

# Attention : à n'utiliser que pour des fichiers de petite taille !
contenu = File.read("mon_document.txt")
puts contenu

Lire un fichier ligne par ligne : File.foreach (recommandé)

C’est la manière la plus efficace et la plus sûre de lire un fichier, surtout s’il est volumineux. File.foreach lit le fichier ligne par ligne, sans jamais le charger entièrement en mémoire. C’est un itérateur qui exécute un bloc pour chaque ligne.

# On suppose un fichier 'courses.txt' avec un article par ligne
File.foreach("courses.txt") do |ligne|
  # 'ligne' contient la ligne actuelle, y compris le caractère de saut de ligne
  puts "À acheter : #{ligne.strip}" # .strip supprime les espaces et sauts de ligne
end

Écrire dans des fichiers

Écrire d’un seul coup : File.write

File.write est le moyen le plus direct d’écrire une chaîne de caractères dans un fichier.

Attention : Par défaut, cette méthode écrase le contenu existant du fichier. Si le fichier n’existe pas, il est créé.

contenu_a_ecrire = "Ceci est la première ligne.\nCeci est la seconde."
File.write("mon_nouveau_fichier.txt", contenu_a_ecrire)

Ajouter du contenu (Append)

Pour ajouter du contenu à la fin d’un fichier sans l’écraser, il faut spécifier le mode: "a" (pour “append”).

File.write("mon_nouveau_fichier.txt", "Une ligne de plus.\n", mode: "a")

La méthode avec bloc : File.open

C’est la manière la plus robuste de travailler avec des fichiers. File.open prend un nom de fichier, un “mode” ("r" pour read, "w" pour write, "a" pour append) et un bloc.

L’énorme avantage est que Ruby garantit que le fichier sera automatiquement fermé à la fin du bloc, même si une erreur se produit à l’intérieur.

# 'w' : mode écriture (write). Le fichier est créé ou écrasé.
File.open("rapport.log", "w") do |fichier|
  # 'fichier' est un objet qui représente le fichier ouvert
  fichier.puts "--- Début du rapport ---"
  fichier.puts "Date : #{Time.now}"
  fichier.puts "----------------------"
end

Bonnes pratiques

  • Pour lire un fichier, préférez File.foreach à File.read, sauf si vous êtes absolument certain que le fichier sera toujours de petite taille.
  • Pour écrire dans un fichier, privilégiez la forme avec un bloc File.open(...) do ... end. C’est le moyen le plus sûr de s’assurer que les fichiers sont correctement fermés.
  • Utilisez des chemins de fichiers construits avec File.join pour la portabilité entre les systèmes d’exploitation (ex: File.join("dossier", "sous_dossier", "fichier.txt")).

Exercices

  1. Écriture simple :

    • Écrivez un script qui crée un fichier hello.txt et qui écrit la phrase “Bonjour, Fichiers !” à l’intérieur.
  2. Lecture et affichage :

    • Écrivez un autre script qui lit le contenu de hello.txt et l’affiche dans la console.
  3. Journalisation :

    • Créez un script logger.rb.
    • Utilisez File.open en mode “append” ("a") pour ajouter une ligne avec la date et l’heure actuelles (Time.now) au fichier app.log à chaque fois que le script est lancé.
    • Lancez le script plusieurs fois et vérifiez le contenu de app.log.
  4. Numéroteur de lignes :

    • Écrivez un script qui lit n’importe quel fichier texte (par exemple, le script lui-même) ligne par ligne, et qui affiche chaque ligne précédée de son numéro.
    • Exemple de sortie :
      1: #!/usr/bin/env ruby
      2:
      3: puts "Hello"
    • Indice : File.foreach a une variante qui donne aussi l’index : File.foreach(file).with_index(1) do |line, line_num| ... end.