Módulo File
El módulo File lee y escribe ficheros de texto y gestiona carpetas: abrir, leer, escribir, copiar, renombrar y borrar ficheros, y crear y borrar carpetas. En una placa, los ficheros van en su memoria flash (LittleFS) o en una tarjeta SD; en Windows, en dos carpetas del proyecto que hacen de flash y de tarjeta.
use File
Plataformas
| Windows | ESP32 / ESP32-S3 | ESP32-P4 | ESP32-S31 | |
|---|---|---|---|---|
flash: | La carpeta del .jxr: Build\flash en un proyecto del IDE | La memoria flash de la placa (LittleFS) | Igual | Igual |
sd: | La carpeta sd de al lado: Build\sd | La tarjeta SD | Igual | Igual |
File.setUnit("sd:") sin tarjeta | La acepta | Da error | Igual | Igual |
La b del modo ("rb", "wb"…) | No traduce los saltos de línea, y deja usar seek en cualquier posición | No cambia nada | Igual | Igual |
| Un modo que no está en la tabla | La VM se cierra | Abre para escribir si lleva w, a o +, y si no, para leer | Igual | Igual |
writeLine acaba la línea con | \r\n (\n si el modo lleva b) | \r\n | \n | \n |
isEOF() | true después de que una lectura intente pasar del final | true en cuanto no queda nada por leer | Igual | Igual |
La memoria flash de la placa se llena con los ficheros del proyecto al pulsar Run, y la tarjeta SD se configura en el perfil de la placa: lo cuenta Pantalla, sonido, SD y red.
Cada Run en una placa vuelve a grabar toda su memoria de ficheros con los del proyecto, y lo que tu programa haya escrito en flash: se pierde (también con Upload Program). La tarjeta SD no se toca. Lo cuenta Grabar el firmware y ejecutar.
Rutas y unidades
Una ruta puede empezar por la unidad, flash: o sd:. Sin unidad, va a la unidad activa, que al empezar el programa es flash: y se cambia con File.setUnit.
use File
var f = File.open("flash:datos.txt", "w") // en la flash
f.close()
var g = File.open("sd:registro.txt", "a") // en la tarjeta SD
g.close()
println(File.exists("datos.txt")) // true: sin unidad, va a la flash
- Las carpetas se separan con
/. Con barra al principio o sin ella, la ruta empieza en la raíz de la unidad:"datos.txt"y"/datos.txt"son el mismo fichero. - En una ruta sin unidad, un
flash/o unsd/al principio se quita:"flash/Images/fondo.bmp"es"Images/fondo.bmp". - Los mensajes de error llevan la ruta completa: en Windows, la carpeta entera del disco; en la placa, la ruta desde la raíz, como
/datos.txt.
Funciones
| Función | Qué hace | Devuelve |
|---|---|---|
File.open(ruta, modo) | Abre un fichero | El fichero abierto |
File.exists(ruta) | Mira si existe un fichero o una carpeta | true o false |
File.delete(ruta) | Borra un fichero | true |
File.rename(ruta, nuevaRuta) | Cambia el nombre de un fichero o lo mueve, en la misma unidad | true |
File.copy(ruta, destino) | Copia un fichero, también de una unidad a otra | true |
File.isDir(ruta) | Mira si la ruta es una carpeta | true o false |
File.mkDir(ruta) | Crea una carpeta | true |
File.rmDir(ruta) | Borra una carpeta vacía | true |
File.size(ruta) | El tamaño de un fichero | Los bytes, un entero |
File.setUnit(unidad) | Cambia la unidad activa | true |
File.getUnit() | La unidad activa | "flash:" o "sd:" |
Si algo falla, lanzan una excepción, que se captura con try (ver Errores y excepciones). Además de los errores de cada una, todas menos getUnit dan ERR_INVALID_ARG_NUMBER si no les pasas los argumentos que piden, y ERR_TYPE_MISMATCH si una ruta no es una cadena.
open(ruta, modo)
Abre el fichero ruta y devuelve el fichero abierto, con los métodos de Objetos que devuelve.
| Modo | Para qué |
|---|---|
"r" | Leer. El fichero tiene que existir. |
"w" | Escribir. Lo crea, o lo vacía si ya existe. |
"a" | Añadir al final. Lo crea si no existe. |
"r+" | Leer y escribir. El fichero tiene que existir. |
"w+" | Leer y escribir. Lo crea, o lo vacía si ya existe. |
"a+" | Leer y añadir al final. |
Cualquiera de ellos puede llevar una b ("rb", "wb", "r+b"…): en Windows, el fichero se lee y se escribe tal cual, sin cambiar los saltos de línea, y seek puede ir a cualquier posición. En las placas, la b no cambia nada.
La carpeta del fichero tiene que existir: File.open no crea carpetas.
| Error | Cuándo |
|---|---|
ERR_FILE_NOT_FOUND | No se puede abrir: con "r", el fichero no existe; con "w" o "a", la carpeta no existe. El mensaje dice la ruta y el modo: Could not open file '…' in mode 'r'. |
ERR_INVALID_VALUE | El modo no es de la tabla, como "rw" o "x". El mensaje dice el modo. |
use File
// Escribir
var f = File.open("salida.txt", "w")
f.writeLine("Hola desde JARU")
f.close()
// Leer
var g = File.open("salida.txt", "r")
println(g.readLine()) // Hola desde JARU
g.close()
exists(ruta)
Devuelve true si existe un fichero o una carpeta con esa ruta, y false si no.
use File
if (File.exists("config.txt")) then
println("El fichero existe")
else
println("No lo encuentro")
end
delete(ruta)
Borra el fichero ruta y devuelve true. Si no existe o no se puede borrar, lanza ERR_FILE_NOT_FOUND. Para borrar una carpeta, usa rmDir.
use File
if (File.exists("temporal.txt")) then
File.delete("temporal.txt")
end
rename(ruta, nuevaRuta)
Cambia el nombre del fichero ruta a nuevaRuta, o lo mueve de carpeta, y devuelve true. Las dos rutas tienen que estar en la misma unidad: para pasar un fichero de la flash a la tarjeta, usa copy y después delete.
| Error | Cuándo |
|---|---|
ERR_INVALID_VALUE | Las rutas son de unidades distintas. |
ERR_FILE_NOT_FOUND | No se puede: el fichero no existe, o la carpeta de destino no existe. |
use File
File.rename("borrador.txt", "final.txt")
copy(ruta, destino)
Copia el fichero ruta en destino y devuelve true. Si destino ya existe, lo sustituye. Puede copiar de una unidad a otra.
| Error | Cuándo |
|---|---|
ERR_FILE_NOT_FOUND | No se puede abrir el fichero de origen, o no se puede crear el de destino (por ejemplo, porque su carpeta no existe). |
ERR_FILE_WRITE_FAIL | Falla la escritura a medias (por ejemplo, porque la unidad se llena). |
use File
File.copy("flash:config.txt", "sd:copias/config.txt") // de la flash a la tarjeta
isDir(ruta)
Devuelve true si ruta es una carpeta, y false si es un fichero o no existe.
use File
if (!File.isDir("registros")) then
File.mkDir("registros")
end
mkDir(ruta)
Crea la carpeta ruta y devuelve true. Crea una sola carpeta: la de arriba tiene que existir. Si no se puede crear, lanza ERR_FILE_WRITE_FAIL; en Windows, también si ya existe (con el mensaje Directory '…' already exists.). Mira antes con exists.
use File
if (!File.exists("registros")) then
File.mkDir("registros")
end
rmDir(ruta)
Borra la carpeta ruta y devuelve true. Tiene que estar vacía: borra antes sus ficheros con delete. Si no está vacía o no existe, lanza ERR_FILE_WRITE_FAIL.
use File
File.rmDir("registros/viejos")
size(ruta)
Devuelve el tamaño del fichero ruta, en bytes. Si no existe, lanza ERR_FILE_NOT_FOUND.
use File
println("Ocupa ", File.size("datos.txt"), " bytes")
setUnit(unidad)
Cambia la unidad activa, la que usan las rutas sin unidad: "flash:" o "sd:". Devuelve true.
| Error | Cuándo |
|---|---|
ERR_INVALID_VALUE | unidad no es "flash:" ni "sd:". |
ERR_FILE_NOT_FOUND | En una placa, pides "sd:" y no hay tarjeta montada. En Windows, "sd:" se acepta siempre. |
use File
File.setUnit("sd:") // desde aquí, las rutas sin unidad van a la tarjeta
var f = File.open("registro.txt", "a")
f.writeLine("Entrada del registro")
f.close()
File.setUnit("flash:") // y desde aquí, otra vez a la flash
getUnit()
Devuelve la unidad activa: "flash:" o "sd:".
use File
println(File.getUnit()) // flash:
Objetos que devuelve
File.open devuelve el fichero abierto. Sus métodos leen y escriben en él desde una posición que avanza con cada lectura o escritura:
| Método | Qué hace | Devuelve |
|---|---|---|
write(texto) | Escribe una cadena | Los caracteres escritos |
writeLine(texto) | Escribe una cadena y un salto de línea | Los caracteres escritos |
read() | Lee desde la posición hasta el final | Una cadena |
readLine() | Lee la línea siguiente, sin el salto de línea | Una cadena, o nil al final |
seek(pos) / seek(pos, origen) | Mueve la posición | 0 si lo consigue |
position() | La posición, en bytes desde el principio | Un entero |
size() | El tamaño del fichero, en bytes | Un entero |
isEOF() | Mira si se ha llegado al final | true o false |
isOpen() | Mira si el fichero sigue abierto | true o false |
close() | Cierra el fichero | nil |
Todos dan ERR_INVALID_ARG_NUMBER si no les pasas los argumentos que piden. Después de close(), todos menos isOpen y close dan error: ERR_FILE_WRITE_FAIL al escribir, ERR_FILE_READ_FAIL al leer y ERR_INVALID_OPERATION en los demás.
write(texto)
Escribe la cadena texto en el fichero y devuelve cuántos caracteres ha escrito. texto tiene que ser una cadena: para escribir un número, conviértelo antes con toString().
Si el fichero se abrió con "r", lanza ERR_FILE_WRITE_FAIL (File was opened in read-only mode ('r').).
writeLine(texto)
Como write, y además acaba la línea. En Windows y en ESP32 y ESP32-S3, la línea acaba en \r\n; en el P4 y el S31, en \n. readLine entiende las dos.
use File
var f = File.open("lista.txt", "w")
f.writeLine("primera")
f.writeLine("segunda")
f.close()
read()
Lee desde la posición hasta el final del fichero y lo devuelve en una cadena. Para leer el fichero entero, llámalo nada más abrirlo, o después de seek(0).
readLine()
Lee la línea siguiente y la devuelve sin el salto de línea, sea \n o \r\n. Al llegar al final, devuelve nil. La última línea se lee aunque no acabe en salto de línea.
use File
var f = File.open("lista.txt", "r")
var linea = f.readLine()
while (linea != nil)
println(linea)
linea = f.readLine()
end
f.close()
seek(pos, origen)
Mueve la posición a pos bytes desde el principio, que es lo de serie. Con origen mide desde otro sitio: 0, el principio; 1, la posición de ahora; 2, el final (con un pos negativo para ir hacia atrás). Un origen que no es ninguno de esos cuenta como 0.
Devuelve 0 si lo consigue y otro número si no. pos y origen tienen que ser enteros (ERR_TYPE_MISMATCH).
En Windows, si el modo no lleva b, solo se puede ir a la posición 0: con otra, lanza ERR_INVALID_OPERATION. Abre el fichero con "rb" para ir a cualquier posición.
use File
var f = File.open("lista.txt", "rb")
f.seek(-8, 2) // 8 bytes antes del final
println(f.position())
f.close()
position()
Devuelve la posición, en bytes desde el principio del fichero.
size()
Devuelve el tamaño del fichero abierto, en bytes, sin mover la posición. Es lo mismo que File.size con su ruta.
isEOF()
Devuelve true si se ha llegado al final del fichero.
En Windows se pone a true después de que una lectura intente pasar del final: después de leer la última línea con readLine sigue en false, y pasa a true cuando readLine devuelve nil. En las placas se pone a true en cuanto no queda nada por leer. Para recorrer un fichero, mira lo que devuelve readLine, no isEOF().
isOpen()
Devuelve true si el fichero está abierto, y false después de close().
close()
Cierra el fichero y devuelve nil. Lo que hayas escrito queda en el disco o en la flash. Cerrarlo otra vez no hace nada.
Ejemplo completo
Un registro de eventos: añade líneas con la hora a un fichero, lo lee entero y dice cuánto ocupa.
use File
// La carpeta del registro
if (!File.exists("registros")) then
File.mkDir("registros")
end
func anotar(mensaje)
var f = File.open("registros/registro.txt", "a")
f.writeLine("[" + time() + "] " + mensaje)
f.close()
end
func mostrar()
if (!File.exists("registros/registro.txt")) then
println("Todavía no hay registro")
return
end
var f = File.open("registros/registro.txt", "r")
var linea = f.readLine()
while (linea != nil)
println(linea)
linea = f.readLine()
end
f.close()
end
anotar("Sistema iniciado")
anotar("Sensor activo")
anotar("Temperatura: 23.5 grados")
mostrar()
println("El registro ocupa ", File.size("registros/registro.txt"), " bytes")
La primera vez, en Windows, imprime algo así (la hora es la del momento; time() la da en texto):
[Fri Nov 6 19:44:07 2026] Sistema iniciado
[Fri Nov 6 19:44:07 2026] Sensor activo
[Fri Nov 6 19:44:07 2026] Temperatura: 23.5 grados
El registro ocupa 140 bytes
Cada vez que lo ejecutas, el registro crece: "a" añade al final.
Trampas y problemas conocidos
- Solo texto.
writeywriteLineescriben cadenas, y una cadena se corta en el primer byte 0: el módulo no sirve para escribir datos binarios.readsí devuelve todos los bytes. seeken Windows, conb. Sin laben el modo,seeksolo va a la posición 0.- No hay forma de listar una carpeta. El módulo no tiene una función que diga qué ficheros hay: guarda tú los nombres, por ejemplo en un fichero índice.
- Las carpetas, de una en una. Ni
mkDirniopencrean las carpetas de arriba. - Cierra los ficheros. Hasta
close(), lo escrito puede no estar todavía en la flash o en la tarjeta.
Todos los problemas conocidos de JARU, juntos, están en Problemas conocidos.