将序列化对象写入文件

Writing an serialized object to a file

我在 将 Java 对象保存到文件 时遇到问题。我正在使用 Android Studio.

编写应用程序

Outgoing是我要保存的对象,里面有两个Strings,一个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());
    }
}

当我启动应用程序时,执行方法save(),应用程序崩溃了。

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

--> 抛出 IOException 并且 Logcat 向我显示:

什么是合适的文件路径?我应该使用哪种数据类型?

感谢您的帮助

如果您收到消息 "Error opening file.",这意味着对 openFile() 的调用失败:

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

ObjectOutputStream 构造函数在这种情况下几乎不会失败,所以问题一定是 new FileOutputStream("outgoings.tmp") 抛出了 IOException,最可能的解释是您没有在当前目录中创建文件的权限。 (其他解释也是可能的....)

要深入了解这一点,您需要修改代码以打印或记录 IOException.

的堆栈跟踪

关于此 "beginner" 代码还应说明的其他几点。

  1. 这样做是个坏主意:

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

    为什么?因为在报错之后,你是在告诉代码继续,就好像什么事都没发生过一样。接下来您将尝试使用 objectOutputStream ... 尚未初始化!

    您应该构建代码,以便您不会应该被您的代码视为致命错误之后继续。

  2. 如果您在 real-life 可能会重复打开文件的程序中执行此操作,那么您很可能会泄露文件描述符。打开和使用文件的正确模式(对于 Java 6 及更高版本)是使用 "try-with-resources" 结构;例如

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

    try 的正文结束时,开始时打开的资源将自动关闭。这种情况 在所有重要的情况下都会发生 。相比之下,如果您手动关闭资源,则存在无法在所有情况下全部关闭的风险。

首先,我们可以尝试在 public 目录中写入,以便使用任何文件管理器应用程序轻松检查结果。

在写入文件系统之前确保 AndroidManifest.xml 包含两个权限请求:

<manifest ...>

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

...
</manifest>

如果您的设备或 emulator/VM 运行 Android 5 或以下,我们可以继续写入文件。如果不是,请查看android developer documentation关于在运行时请求权限的部分。

这里有一些代码可以以 95% 的概率为您提供可写目录:

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

所以现在你可以尝试在那里写一个文件

fileOutputStream = new FileOutputStream(new File(destination, "outgoings.tmp"));
//write there anything you want