Bibliothèque io

La bibliothèque io donne accès aux fichiers et flux du système hôte : ouverture/lecture/écriture de fichiers, entrée/sortie standard, énumération de dossiers.

Prérequis : une bibliothèque non ouverte automatiquement

Contrairement à coroutine/package/regex/debug, io n'est pas incluse dans OpenLibs() : toutes ses fonctions délèguent à l'hôte .NET (IScriptHost.StandardInput/StandardOutput/ StandardError/OpenFile/...), et tous les hôtes ne veulent pas donner à un script un accès complet au système de fichiers. L'hôte doit appeler explicitement OpenIOLib() pour l'activer :

// côté hôte .NET
script.OpenLibs();
script.OpenIOLib();   // active 'io' pour ce moteur

Si l'hôte n'a pas ouvert la bibliothèque, require("io") échoue comme n'importe quel searcher qui ne trouve pas de module (l'erreur remonte comme une erreur script normale — utilisez pcall(require, "io") pour la récupérer sous forme de nil, message) :

local ok, err = pcall(require, "io")
if not ok then
    print("io indisponible : " .. tostring(err))
end

Vue d'ensemble

Fonction / méthode Description
io.open(filename [, mode [, encoding]]) Ouvre un fichier, retourne un objet file
io.popen(command [, mode [, encoding]]) Ouvre un pipe vers une commande shell (si l'hôte le permet)
io.tmpfile() Ouvre un fichier temporaire auto-supprimé à la fermeture
io.close([file]) Ferme file (par défaut la sortie courante)
io.read(...) Lit depuis l'entrée courante
io.write(...) Écrit vers la sortie courante
io.flush() Vide le tampon de la sortie courante
io.lines([filename, ...]) Itérateur de lignes sur filename (ou l'entrée courante)
io.input([file]) Lit/fixe le fichier d'entrée par défaut
io.output([file]) Lit/fixe le fichier de sortie par défaut
io.type(obj) "file" / "closed file" / nil
io.exists(path) Teste l'existence d'un fichier
io.direxists(path) Teste l'existence d'un dossier
io.mkdir(path) Crée un dossier (et ses parents manquants)
io.rmdir(path [, recursive]) Supprime un dossier
io.listdir(path) Liste le contenu direct d'un dossier
io.sha256file(path) Empreinte SHA-256 (hex) du contenu d'un fichier
io.encodings() Liste des encodages utilisables en 3ᵉ argument de io.open
file:read(...) Lit depuis file
file:write(...) Écrit dans file
file:seek([whence [, offset]]) Déplace/lit la position courante dans file
file:truncate([size]) Tronque file à size octets (défaut : position courante)
file:flush() Vide le tampon de file
file:lines(...) Itérateur de lignes sur file
file:close() Ferme file
file:setvbuf(...) Pas de tampon applicatif à configurer — accepté mais sans effet
io.stdin, io.stdout, io.stderr Objets file liés à l'entrée/sortie/erreur standard de l'hôte

L'objet file

io.open/io.popen/io.tmpfile retournent un objet file (un userdata, dans le même esprit qu'un FILE* en C). Il doit être refermé explicitement par file:close(), implicitement via l'attribut <close>, ou en dernier recours par le ramasse-miettes. Utiliser une méthode sur un fichier déjà fermé lève une erreur (Err_FileHandleClosed).

local f <close> = io.open("data.txt", "r")
-- f:close() est appelé automatiquement en sortie de bloc

io.open(filename [, mode [, encoding]])

Ouvre filename. mode (chaîne, défaut "r") :

Mode Accès
"r" Lecture seule
"w" Écriture, écrase le contenu existant
"a" Écriture en ajout (append)
"r+" Lecture/écriture, le fichier doit exister
"w+" Lecture/écriture, écrase le contenu existant
"a+" Lecture/écriture en ajout

Un suffixe "b" (ex. "rb") ouvre en mode binaire : chaque octet (0-255) correspond à exactement un caractère de la chaîne script (encodage ISO-8859-1 forcé en interne, exposé sous le nom "binary") — le 3ᵉ argument encoding est alors ignoré silencieusement, un mode binaire ne serait plus byte-safe sinon.

encoding (nom ou numéro de codepage, résolu par l'hôte — voir io.encodings()) contrôle l'encodage texte utilisé en mode non-binaire ; par défaut, celui de l'hôte (UTF-8 en général).

En cas d'échec (fichier absent en lecture, permission refusée, erreur disque...), retourne nil plus un message d'erreur plutôt que de lever une erreur :

local f, err = io.open("introuvable.txt", "r")
if not f then print("échec : " .. err) end

io.popen(command [, mode [, encoding]])

Ouvre un pipe vers command, exécutée par le shell de l'hôte. mode est "r" (lit la sortie de la commande, défaut) ou "w" (écrit vers son entrée). Refusé (nil, message d'erreur) si l'hôte ne supporte pas l'exécution de commandes (IScriptHost.HasCommandShell).

Fermer un handle popen (:close(), <close>, __gc) rapporte le statut de sortie du processus enfant, comme en Lua : true/nil selon le succès, "exit" (ou "signal") plus le code. Une différence toutefois — "signal" n'est rapporté que si le processus n'a pas quitté de lui-même dans un délai raisonnable et a dû être tué de force côté hôte (Process.Kill) : .NET n'expose pas, de façon portable, une vraie information de signal POSIX.

io.tmpfile()

Ouvre un nouveau fichier temporaire en mode "wb+", supprimé par l'hôte dès que le dernier handle vers lui se ferme (:close(), <close>, __gc, ou même la simple fin du processus).

io.close([file]) / file:close()

Ferme file (par défaut, la sortie courante — io.output()). Retourne true. Idempotent — refermer un fichier déjà fermé ne fait rien de plus.

io.read(...) / file:read(...)

Lit depuis l'entrée courante (io.read) ou depuis file (file:read), selon un ou plusieurs formats :

Format Résultat
"l" (ou omis) Ligne suivante, sans le retour à la ligne — nil en fin de fichier
"L" Ligne suivante, retour à la ligne inclus — nil en fin de fichier
"a" Tout le reste du fichier (chaîne vide si déjà à la fin, jamais nil)
"n" Un nombre (entier ou flottant) lu au fil du texte — nil si aucun nombre
un entier n Au plus n caractères — nil seulement si aucun caractère n'a pu être lu

Le préfixe "*" ("*l", "*a"...) est accepté par compatibilité et ignoré. Sans argument, équivaut à read("l").

local f = io.open("data.txt", "r")
for line in f:lines() do print(line) end

io.write(...) / file:write(...)

Écrit chaque argument (chaîne ou nombre) vers la sortie courante ou file, sans séparateur ni saut de ligne ajouté. Retourne le fichier écrit (chaînable).

io.flush() / file:flush()

Force l'écriture du tampon vers le support sous-jacent.

io.lines([filename, ...]) / file:lines(...)

Retourne un itérateur for sur les lignes de filename (ouvert et refermé automatiquement à la fin de l'itération) ou de l'entrée courante si filename est omis. Les arguments suivants sont des formats de lecture (mêmes lettres que io.read), un par valeur retournée à chaque itération ; par défaut, une seule valeur au format "l".

file:lines(...) fait la même chose sur un fichier déjà ouvert, sans jamais le refermer automatiquement en fin d'itération (contrairement à io.lines(filename, ...)).

io.input([file]) / io.output([file])

Sans argument, retournent le fichier d'entrée/sortie par défaut actuel. Avec un nom de fichier, l'ouvrent (lecture pour input, écriture pour output) et le fixent comme nouveau défaut. Avec un objet file déjà ouvert, le fixent directement comme défaut. Retournent le fichier résultant.

file:seek([whence [, offset]])

Déplace (ou lit, avec offset = 0) la position courante dans file. whence : "set" (depuis le début), "cur" (défaut, depuis la position courante), "end" (depuis la fin). Retourne la nouvelle position, ou nil plus un message d'erreur en cas d'échec.

file:truncate([size])

Tronque (ou étend) file à size octets (par défaut, la position courante — sémantique ftruncate POSIX). Retourne true, ou nil plus un message d'erreur en cas d'échec.

file:setvbuf(...)

Accepté (pour compatibilité de code Lua existant) mais sans effet : les écritures vont directement au flux sous-jacent, il n'y a pas de tampon applicatif à configurer.

io.type(obj)

Retourne "file" si obj est un fichier ouvert, "closed file" s'il est fermé, ou nil si obj n'est pas un objet file de ce module.

io.exists(path) / io.direxists(path)

Testent respectivement l'existence d'un fichier / d'un dossier à path.

io.mkdir(path)

Crée path, y compris les dossiers parents manquants ; ne fait rien si path existe déjà. Retourne true, ou nil plus un message d'erreur en cas d'échec.

io.rmdir(path [, recursive])

Supprime le dossier path. recursive (défaut false) : si false et que path n'est pas vide, c'est un échec plutôt qu'un vidage silencieux. Retourne true, ou nil plus un message d'erreur.

io.listdir(path)

Retourne un tableau (indices 1..n) des entrées directes (non récursif) de path, chacune une table { name=, isdirectory=, size=, lastmodified= } (lastmodified en epoch secondes, même unité que os.time()).

io.sha256file(path)

Calcule l'empreinte SHA-256 du contenu du fichier path, retournée en hexadécimal minuscule. Lit le fichier en flux binaire, sans passer par une conversion texte intermédiaire.

io.encodings()

Retourne un tableau des encodages que l'hôte sait résoudre pour le 3ᵉ argument de io.open/ io.popen, chacun { codepage=, name=, displayname= }. Inclut toujours l'entrée pseudo-encodage "binary" en plus de ce que rapporte l'hôte.

io.stdin, io.stdout, io.stderr

Objets file déjà ouverts, liés à l'entrée/sortie/erreur standard fournies par l'hôte. io.stdin est le défaut initial de io.input(), io.stdout celui de io.output().