Tengo problemas para guardar un objeto Java en un archivo . Estoy escribiendo la aplicación con Android Studio .

Saliente es el objeto que quiero guardar, contiene dos Strings y un int.

private FileOutputStream fileOutputStream;
private ObjectOutputStream objectOutputStream;

public void save(String name, String category, int price){

    // Open file
    try {
        fileOutputStream = new FileOutputStream("outgoings.tmp");
        objectOutputStream = new ObjectOutputStream(fileOutputStream);
    } catch (IOException ioException) {
        System.err.println(ioException.getMessage());
    }

    // Saving
    Outgoing record;
    Scanner input = new Scanner(System.in);

    while (input.hasNext()) {
        try{
            if(name != null){
                record = new Outgoing(name, category, price);
                objectOutputStream.writeObject(record);
            }
        }
        catch(IOException ioException){
            System.err.println(ioException.getMessage());
        }
    }

    // Close file
    try{
        objectOutputStream.close();
    }
    catch (IOException ioException) {
        System.err.println(ioException.getMessage());
    }
}

Cuando estoy iniciando la aplicación, ejecuto el método save(), la aplicación se bloquea.

// Open file
try {
    fileOutputStream = new FileOutputStream("outgoings.tmp");
    objectOutputStream = new ObjectOutputStream(fileOutputStream);
} catch (IOException ioException) {
    System.err.println(ioException.getMessage());
}

-> se lanza la IOException y Logcat me muestra esto:

Logcat

¿Cuál sería una ruta de archivo adecuada y qué tipo de datos debería usar?

gracias por su ayuda

1
Pascal Burkard 16 feb. 2018 a las 15:35

2 respuestas

La mejor respuesta

En primer lugar, podemos intentar escribir en un directorio público para que los resultados se puedan verificar fácilmente con cualquier aplicación de administración de archivos.

Antes de escribir en el sistema de archivos, asegúrese de que AndroidManifest.xml contenga dos solicitudes de permiso:

<manifest ...>

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

...
</manifest>

Podemos proceder a escribir archivos si su dispositivo o emulador / VM ejecuta Android 5 o inferior. Si no es así, consulte la parte de la documentación para desarrolladores de Android sobre la solicitud de permisos en tiempo de ejecución.

Aquí hay un código que le dará un directorio grabable con un 95% de probabilidad:

File destination = new File(Environment.getExternalStorageDirectory(), "My Cool Folder");
destination.mkdirs();

Así que ahora puedes intentar escribir un archivo allí.

fileOutputStream = new FileOutputStream(new File(destination, "outgoings.tmp"));
//write there anything you want
0
Rawnald Gregory Erickson 17 feb. 2018 a las 01:49

Si recibe el mensaje "Error opening file.", eso significa que la llamada a openFile() ha fallado:

public void openFile() {
    try {
        fileOutputStream = new FileOutputStream("outgoings.tmp");
        objectOutputStream = new ObjectOutputStream(fileOutputStream);
    } catch (IOException ioException) {
        System.err.println("Error opening file.");
    }

El constructor ObjectOutputStream prácticamente no puede fallar en este contexto, por lo que el problema debe ser que new FileOutputStream("outgoings.tmp") arrojó el IOException, y la explicación más probable es que no tienes permiso para crear un archivo en el directorio actual. (Otras explicaciones son posibles ...)

Para llegar al final de esto, necesita modificar su código para imprimir o registrar el seguimiento de la pila para IOException.


Un par de otros puntos que deberían hacerse sobre este código para "principiantes".

  1. Hacer esto es una mala idea:

    } catch (IOException ioException) {
        System.err.println("Error opening file.");
    }
    

    ¿Por qué? Porque después de informar el error, le está diciendo al código que continúe como si nada. Y lo siguiente que intentará hacer es usar objectOutputStream ... ¡que no ha sido inicializado!

    Debe estructurar el código de modo que no continúe después de lo que debería ser tratado como un error fatal por su código.

  2. Si hace esto en un programa de la vida real que potencialmente abre archivos repetidamente, es probable que filtre descriptores de archivos. El patrón correcto para abrir y usar archivos (para Java 6 y posteriores) es usar la construcción "try-with-resources"; p.ej.

    try (FileOutputStream out = new FileOutputStream(...)) {
        // write stuff
    }
    

    cuando el cuerpo de try finaliza, los recursos que se abrieron al principio se cerrarán automáticamente. Esto sucede en todas las circunstancias importantes . Por el contrario, si cierra los recursos manualmente, existe el riesgo de que no se cierren todos en todas las circunstancias.

1
Stephen C 17 feb. 2018 a las 00:30