En muchos casos se necesita leer y escribir archivos a las unidades de almacenamiento del teléfono. Uno de los escenarios posibles es la exportación e importación de datos.
En esta nota voy a mostrar breves ejemplos de como realizar estas tareas utilizando la API FileConnection.
La clase FileConnection forma parte de los paquetes opcionales a J2ME. Por ese motivo al crear un nuevo proyecto en Sun Wireless Toolkit, al momento de elegir la API, debemos marcar:
Target Platform = JTWI y tildar PDA Profile for J2ME (JSR 75)

Hay que destacar que al ser una especificación optativa puede no estar presente en todos los teléfonos o dispositivos. En general todos los teléfonos actuales lo soportan, pero no es así para los modelos viejos.
En el emulador el sistema de archivos "virtual" se encuentra en la carpeta "..j2mewtk\2.5.2\appdb\DefaultColorPhone\filesystem\".
Dentro de esta carpeta podemos encontrar otra llamada root1. Cada carpeta en "filesystem" es tomada como una unidad o root por el emulador. En el télefono cada root corresponderá a un dispositivo de almacenamiento diferente, en la mayoría de los casos uno será la memoria interna del teléfono y otro la tarjeta de memoria.
El primer ejemplo trata de como listar todos los roots disponibles. Esto se logra utilizando la clase FileSystemRegistry:
public void SelectRoot() {
Enumeration rootListEnum = FileSystemRegistry.listRoots();
listRoots = new List("Elija el root:", Choice.EXCLUSIVE);
while (rootListEnum.hasMoreElements()) {
String rootName = (String) rootListEnum.nextElement();
listRoots.append(rootName, null);
}
...
Este fragmento utiliza la función listRoots() que devuelve una lista de los roots y luego la carga en un control de lista para mostrarla en la pantalla.
Para listar el contenido de un directorio:
Display.getDisplay(this).setCurrent(WaitForm);
Thread t = new Thread() {
public void run() {
try{
FileConnection myFc = (FileConnection)
Connector.open("file:///" + currentRoot);
Enumeration fileEnum = myFc.list("*", false);
while(fileEnum.hasMoreElements()) {
String fileName = (String) fileEnum.nextElement();
listContents.append(fileName, null);
}
} catch (Throwable th) {
System.out.println(th.toString());
}
}
};
t.start();
Las tres primeras líneas son obligatorias cuando estemos utilizando un CommandListener por lo expuesto en
Acceso a archivos y threads, su finalidad es evitar que la aplicación se cuelgue si hay un problema en las operaciones de manejo de archivos.
En lo demás este caso es similar al de listado de roots, utilizando el método "list".
Finalmente para escribir un archivo debemos utlizar además un Data Stream:
Thread t = new Thread() {
public void run() {
try{
FileConnection conn = (FileConnection) Connector.open(writeFile, Connector.READ_WRITE);
if (!conn.exists()) {
conn.create();
}
OutputStream outSt = conn.openOutputStream();
PrintStream printSt = new PrintStream(outSt);
printSt.println(writeContents);
conn.close();
} catch(IOException e) {
System.out.println("IOException in WriteToFile: " + e.toString());
} catch(SecurityException e) {
System.out.println("SecurityException in WriteToFile: " + e.toString());
}
}
};
t.start();
La referencia de este paquete opcional se encuentra en:
JSR-000075 PDA Optional Packages for the J2METM Platform. Ahí puede descargarse las especificaciones de FileConnection con todas sus clases y métodos.
Y una serie de artículos sobre esto en:
Mobile Service Architecture - JSR 75
El código completo de esta clase ejemplo es:
import javax.microedition.midlet.MIDlet;
import javax.microedition.io.file.*;
import java.io.*;
import java.util.*;
import javax.microedition.io.*;
import javax.microedition.lcdui.*;
public class FileDemo extends MIDlet implements CommandListener {
List listRoots, listContents;
private String currentRoot, currentPath, writeFile, writeContents;
private Command cmOK,cmExit, cmNew;
private Form WaitForm;
public void FileDemo() {
}
public void startApp() {
WaitForm = new Form("Espere por favor...");
WaitForm.setCommandListener(this);
cmExit = new Command("Exit", Command.EXIT, 1);
cmNew = new Command("New", Command.ITEM,2);
SelectRoot();
}
public void pauseApp() {
}
public void destroyApp(boolean condition) {
notifyDestroyed();
}
public void SelectRoot() {
Enumeration rootListEnum = FileSystemRegistry.listRoots();
listRoots = new List("Elija el root:", Choice.EXCLUSIVE);
while (rootListEnum.hasMoreElements()) {
String rootName = (String) rootListEnum.nextElement();
listRoots.append(rootName, null);
}
cmOK = new Command("OK", Command.ITEM, 1);
listRoots.addCommand(cmOK);
listRoots.addCommand(cmExit);
listRoots.setCommandListener(this);
Display.getDisplay(this).setCurrent(listRoots);
}
public void ShowContents() {
listContents = new List("Contenidos de " + currentRoot, Choice.EXCLUSIVE);
Display.getDisplay(this).setCurrent(WaitForm);
Thread t = new Thread() {
public void run() {
try{
FileConnection myFc = (FileConnection)
Connector.open("file:///" + currentRoot);
Enumeration fileEnum = myFc.list("*", false);
while(fileEnum.hasMoreElements()) {
String fileName = (String) fileEnum.nextElement();
listContents.append(fileName, null);
}
} catch (Throwable th) {
System.out.println(th.toString());
}
}
};
t.start();
listContents.addCommand(cmExit);
listContents.addCommand(cmNew);
listContents.setCommandListener(this);
Display.getDisplay(this).setCurrent(listContents);
}
public void WriteToFile(String fileName, String contents) {
writeFile = fileName;
writeContents = contents;
Thread t = new Thread() {
public void run() {
try{
FileConnection conn = (FileConnection) Connector.open(writeFile, Connector.READ_WRITE);
if (!conn.exists()) {
conn.create();
}
OutputStream outSt = conn.openOutputStream();
PrintStream printSt = new PrintStream(outSt);
printSt.println(writeContents);
conn.close();
} catch(IOException e) {
System.out.println("IOException in WriteToFile: " + e.toString());
} catch(SecurityException e) {
System.out.println("SecurityException in WriteToFile: " + e.toString());
}
}
};
t.start();
}
public void commandAction(Command cm, Displayable d) {
//System.out.println("En commandAction");
if (cm == cmOK && d == listRoots) {
System.out.println("Elegiste: " + listRoots.getString(listRoots.getSelectedIndex()));
currentRoot = listRoots.getString(listRoots.getSelectedIndex());
ShowContents();
} else if (cm == cmExit) {
destroyApp(false);
} else if (cm == cmNew) {
WriteToFile("file:///" + currentRoot + "newfile.txt","Sample, sample, sample");
}
}
}