Manejo de archivos - jackgris/wikiLibGDX_es GitHub Wiki

6 Manejo de archivos


Introduccion

Las aplicaciones Libgdx se ejecutan en cuatro plataformas diferentes: sistemas de escritorio (Windows, Linux, Mac OS X, headless), Android, IOS, y JavaScript/WebGL en los navegadores que lo soporten. Cada una de estas plataformas maneja el I/O de archivos un poco diferente.

El módulo Files (el código) de Libgdx nos provee la habilidad de:

  • Leer un archivo
  • Escribir un archivo
  • Copiar un archivo
  • Mover un archivo
  • Eliminar un archivo
  • Listar los archivos y directorios
  • Comprobar si existe un directorio/archivo

Antes de poder sumergirnos en este aspecto de Libgdx, tenemos que revisar primero algunas nociones de los sistemas de archivos soportados en las diferentes plataformas.

Sistemas de Ficheros segun la Plataforma

Aquí vamos a revisar algunos paradigmas de los diferentes sistemas de archivos que soporta Libgdx.

Escritorio o Desktop (Windows, Linux, Mac OS X, Headless)

En un sistema operativo de escritorio, el sistema de archivos es una gran parte de la memoria. Los archivos pueden ser referenciados con rutas relativas al directorio actual de trabajo (el directorio donde se ejecuta la aplicación) o la ruta absoluta. Ignorando los permisos de los archivos, los archivos y directorios se suelen poder leer y escribir por todas las aplicaciones.

Android

En Android la situación es un poco más compleja. Los archivos pueden ser almacenados en el interior del APK de la aplicación como un recurso o como un assets. Estos archivos son de solo lectura. Libgdx unicamente usa el mecanismo de assets, ya que proporciona un acceso más puro a los streams de bytes y se asemeja más a un sistema tradicional de archivos. Los Resources(recursos) son mejores para aplicaciones Android normales, pero presentan problemas cuando se utilizan en juegos. Android los manipula en tiempo de carga, así por ejemplo puede redimensionar automaticamente las imágenes.

Los Assets son guardados en el directorio assets de su proyecto Android y será empaquetado en su APK automaticamente cuando realice el deploy de la aplicación. Ninguna otra aplicación podrá acceder a estos archivos.

Los archivos también se pueden guardar en la memoria interna, donde serán de lectura y escritura. Cada aplicación instalada tiene un directorio dedicado en el almacenamiento interno. Nuevamente este directorio es unicamente accesible por la aplicación. Uno puede pensar en esto como un área de trabajo de la aplicación de almacenamiento privado.

Por último, los archivos se pueden almacenar en el almacenamiento externo, como una tarjeta SD. El almacenamiento externo no siempre puede estar disponible, por ejemplo, el usuario puede sacar la tarjeta SD. Los archivos en esta ubicación de almacenamiento por lo tanto deben ser considerados volátiles. Usted tendrá que agregar los permisos a su archivo AndroidManifest.xml que le permitan escribir en el almacenamiento externo, consulte Permisos.

IOS

En iOS todos los tipos de archivos están disponibles.

Javascript/WebGL

Una aplicación pura en Javascript/WebGL no tiene un concepto de sistema de archivos tradicional. En lugar de ello, los assets como imágenes son referenciados por las direcciones URL que apuntan a archivos en uno o más servidores. Los navegadores modernos también soportan el almacenamiento local que se acerca a lo que es una lectura/escritura de un sistema de archivos tradicional.

Libgdx hace algo de magia bajo el capó para ofrecerle una abstracción del sistema de archivos de sólo lectura.

Tipos de Archivos (almacenamiento)

Un archivo en libgdx está representado por una instancia de la clase FileHandle. Un FileHandle tiene un tipo que define dónde se encuentra el archivo. La siguiente tabla indica la disponibilidad y ubicación de cada tipo de archivo para cada plataforma.

Tipo Descripción, ruta del archivo y características Desktop Android HTML5 iOS
Classpath Los archivos de Classpath se almacenan directamente en sus carpetas de origen. Estos quedan empaquetados en sus jars y son siempre de sólo lectura. Ellos tienen su propósito, pero se deben evitar si es posible. Si Si No Si
Interno Los archivos internos están en relación con la raíz de la aplicación o el directorio de trabajo en equipos de escritorio, en relación con el directorio de assets en Android, y en relación con el directorio war/assets/ en su proyecto GWT. Estos archivos son de sólo lectura. Si un archivo no se puede encontrar en la memoria interna, el módulo de archivo cae de nuevo a buscar el archivo en la ruta del classpath. Esto es necesario si se utiliza la carpeta de recursos vinculando el mecanismo de Eclipse, consulte Configuración del proyecto Si Si Si Si
Local Los archivos locales se almacenan relativos a la raíz de la aplicación o el directorio de trabajo en equipos de escritorio y en relación con el almacenamiento interno (privada) a la aplicación en Android. Tenga en cuenta que local e interno son en su mayoría lo mismo en el escritorio. Si Si No Si
Externo Los archivos externos son relativos a la ruta de la raíz de la tarjeta SD en Android y al directorio home de el usuario actual en los sistemas de escritorio. Si Si No Si
Absoluto Los archivos absolutos necesitan tener espesificadas sus rutas de acceso completas.
Tenga en cuenta: Por el bien de la portabilidad, esta opción debe ser usada solo cuando sea absolutamente necesario
Si Si No Si

Los archivos en el classpath y absolutos se utilizan sobre todo por herramientas tales como editores de escritorio, que tienen requisitos más complejo de i/o sobre los archivos. Para los juegos estos pueden ser ignorados. El orden en que se deben utilizar estos tipos es de la siguente forma:

  • Archivos internos: todos los assets (imágenes, archivos de audio, etc) que se suministran con la aplicación son archivos internos. Si utiliza la interfaz de usuario de configuración, simplemente con soltarlos en la carpeta de assets de su proyecto Android.
  • Archivos locales: si necesita escribir archivos pequeños por ejemplo guardar un estado de juego, debe utilizar archivos locales. Estos son, en general, privados a su aplicación. Si quieres guardar claves/valor en su lugar, también puede mirar en Preferences.
  • Archivos externos: si usted necesita escribir archivos de gran tamaño, por ejemplo, imágenes, o archivos descargados de la Web, deben ir en el almacenamiento externo. Tenga en cuenta que el almacenamiento externo es volátil, un usuario puede quitar o eliminar los archivos que usted escribió.

Comprobacion de la disponibilidad de almacenamiento y acceso

Los diferentes tipos de almacenamiento pueden no estar disponibles en función de la plataforma en que la aplicación se ejecuta. Puede consultar este tipo de información a través del módulo Files:

boolean isExtAvailable = Gdx.files.isExternalStorageAvailable();
boolean isLocAvailable = Gdx.files.isLocalStorageAvailable();

También puede consultar la ruta a la raíz de almacenamiento externo y local:

String extRoot = Gdx.files.getExternalStoragePath();
String locRoot = Gdx.files.getLocalStoragePath();

Obteniendo el FileHandles

Un FileHandle se obtiene mediante el uso de uno de los tipos antes mencionados directamente desde el módulo Files. El siguiente código obtiene un handle para el archivo interno myfile.txt.

FileHandle handle = Gdx.files.internal("data/myfile.txt");

Si ha utilizado la configuración de UI, este archivo se encuentrará en la carpeta assets de su proyecto Android, $ANDROID_PROJECT/assets/data para ser exactos. Sus proyectos de escritorio y html enlazan a esta carpeta en Eclipse, y lo recogerá de forma automática cuando se ejecuta desde dentro de Eclipse.

FileHandle handle = Gdx.files.classpath("myfile.txt");

El archivo "myfile.txt" se encuentra en el directorio en el que las clases compiladas residen o los donde los archivos jar están incluidos.

FileHandle handle = Gdx.files.external("myfile.txt");

En este caso, "myfile.txt" tiene que estar en el directorio home del usuario (/home/<user>/myfile.txt en Linux, /Users/<user>/myfile.txt en OSX y C:\Users\<user>\myfile.txt en Windows) en el escritorio y en la raíz de la tarjeta SD en Android.

FileHandle handle = Gdx.files.absolute("/some_dir/subdir/myfile.txt");

En el caso del handle de archivos absoluto, el archivo tiene que estar exactamente dónde está la ruta completa. En /some_dir/subdir/ de la unidad actual en Windows o la ruta exacta en Linux, MacOS y Android.

Las instancias FileHandle se pasan a los métodos de las clases de la son responsables de leer y escribir datos. Por ejemplo un FileHandle debe especificarse cuando se carga una imagen a través de la clase de Texture, o cuando se carga un archivo de audio a través del módulo Audio.

Listar y Comprobar las propiedades de los archivos

A veces es necesario comprobar la existencia de un archivo específico o listar el contenido de un directorio. FileHandle nos proporciona métodos para hacer precisamente eso de una manera concisa.

He aquí un ejemplo que comprueba si existe un archivo específico y si un archivo es un directorio o no.

boolean exists = Gdx.files.external("doitexist.txt").exists();
boolean isDirectory = Gdx.files.external("test/").isDirectory();

El listar un directorio es igualmente simple:

FileHandle[] files = Gdx.files.local("mylocaldir/").list();
for(FileHandle file: files) {
   // do something interesting here
}

Nota: El listado de directorios internos no es soportado en aplicaciones de escritorio.

También podemos pedir el directorio padre de un archivo o crear una FileHandle de un archivo en un directorio (también conocido como "child").

FileHandle parent = Gdx.files.internal("data/graphics/myimage.png").parent();
FileHandle child = Gdx.files.internal("data/sounds/").child("myaudiofile.mp3");

parent apuntaría a "data/graphics/", el hijo (child) señalaría a "data/sounds/myaudiofile.mp3".

Hay muchos más métodos en FileHandle que le permiten comprobar si hay atributos específicos de un archivo. Por favor, consulte el Javadocs para más detalles.

Nota: Estas funciones en su mayoría no están implementadas para el back-end de HTML5 por el momento. Trate realmente de no confiar en ellos si su obejetivo será una aplicación HTML5.

Manejo de errores

Algunas operaciones sobre FileHandles pueden fallar. Adoptamos RuntimeExceptions para las señales de errores en lugar de comprobar Excepciones. Nuestro razonamiento es el siguiente: el 90% del tiempo que va a acceder a los archivos sabemos que existen y son legibles (por ejemplo, archivos internos empaquetados ​​con nuestra aplicación).

Leer de un archivo

Después de obtener un FileHandle, nosotros tampoco podemos pasar a una clase que sabe cómo cargar el contenido del archivo (por ejemplo, una imagen), o leerla por nosotros mismos. Esto último se realiza a través de cualquiera de los métodos de entrada en la clase FileHandle. El siguiente ejemplo ilustra cómo cargar texto desde un archivo interno:

FileHandle file = Gdx.files.internal("myfile.txt");
String text = file.readString();

Si tiene datos binarios, puede fácilmente cargar el archivo en un array {{{byte[]}}}:

FileHandle file = Gdx.files.internal("myblob.bin");
byte[] bytes = file.readBytes();

La clase FileHandle tiene muchos más métodos de lectura. Compruebe el Javadocs para más información.

Escribir en un archivo

Al igual que la lectura de archivos, FileHandle también proporciona métodos para escribir en un archivo. Tenga en cuenta que sólo los tipos de archivos locales, externos y absolutos soportan escribir en un archivo. Escribir una cadena en un archivo funciona de la siguiente manera:

FileHandle file = Gdx.files.local("myfile.txt");
file.writeString("My god, it's full of stars", false);

El segundo parámetro de FileHandle#WriteString especifica si el contenido se debe anexar al archivo. Si se establece en false, se sobrescribe el contenido actual del archivo.

Uno puede, por supuesto también escribir datos binarios en un archivo:

FileHandle file = Gdx.files.local("myblob.bin");
file.writeBytes(new byte[] { 20, 3, -2, 10 }, false);

Hay muchos más métodos en FileHandle que facilitan la escritura de diferentes maneras, por ejemplo, utilizando OutputStream. Una vez más, consulte el Javadocs para más detalles.

Como eliminar, copiar, renombrar y mover archivos/directorios

Estas operaciones nuevamente sólo son posible para los tipos de archivo de escritura (locales, externos, absolutos). Tenga en cuenta sin embargo, que la fuente para una operación de copia también puede ser un FileHandle de sólo lectura. Algunos ejemplos:

FileHandle from = Gdx.files.internal("myresource.txt");
from.copyTo(Gdx.files.external("myexternalcopy.txt");

Gdx.files.external("myexternalcopy.txt").rename("mycopy.txt");
Gdx.files.external("mycopy.txt").moveTo(Gdx.files.local("mylocalcopy.txt"));

Gdx.files.local("mylocalcopy.txt").delete();

Tenga en cuenta que la fuente y destino pueden ser archivos o directorios.

Para obtener más información sobre los métodos disponibles, verifique el Javadocs de FileHandle.

Enlaces

⚠️ **GitHub.com Fallback** ⚠️