gpt4 book ai didi

java - 如何更新由 openFileOutput 创建的文件

转载 作者:太空狗 更新时间:2023-10-29 12:55:55 25 4
gpt4 key购买 nike

我目前正在构建一个应用程序,用户将随着时间的推移生成数据,如果他/她有互联网连接,则将其传输到网络。但是,如果他没有网络访问权限,我需要将这些数据存储在手机中,直到用户恢复他的访问权限,那时我需要恢复这些数据以进行传输。但是,我在执行此操作时遇到了很多麻烦,如下所示。

注意:首先,我使用的是本地 java 创建的文件,因为我不知道其他方法可以在设备上保存/恢复这些数据。如果您碰巧知道从设备内存储/访问此数据的任何其他方式,请随时在此处发表评论。

仅供引用,

  • phantoms 是一个 ArrayList 包含我需要的数据的对象
    商店,
  • Arquivador 是我用来使我的数据持久化并恢复它的类,
  • Funcionario 是程序生成数据的类(只是几个字符串和数字)

  • 我可以通过下面的代码在我的 Activity 中将文件写入文件系统:
    try {
    arq = new Arquivador();
    arq.addFirstObjectInFile(
    openFileOutput("dados.jlog", MODE_WORLD_WRITEABLE),
    phantoms.get(0));
    phantoms.remove(phantoms.get(0));
    for (Funcionario func : phantoms) {
    arq.addObjectInFile(openFileOutput("dados.jlog", MODE_APPEND),
    func);
    }
    } catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    }

    这是 Arquivador中的代码将数据添加到文件中:
    public void addObjectInFile(FileOutputStream arquivo,
    Object objetoAAdicionar) {
    try {
    ObjectOutputStream aoos = new ObjectOutputStream(arquivo);
    aoos.writeObject(objetoAAdicionar);
    aoos.close();
    } catch (IOException ioe) {
    Log.d(TAG_NAME, "Erro no Appendable OOS.");
    }
    }

    public void addFirstObjectInFile(FileOutputStream arquivo,
    Object objetoAAdicionar) {
    try {
    AppendableObjectOutputStream aoos = new AppendableObjectOutputStream(
    arquivo);
    aoos.writeObject(objetoAAdicionar);
    aoos.close();
    } catch (IOException ioe) {
    Log.d(TAG_NAME, "Erro no Appendable OOS.");
    }
    }

    您会注意到我分两步将数据添加到持久性中,第一个 Object 和其余的。这是我看到的一个想法 on this post ,在 StackOverflow 中,允许将数据附加到 Java 生成的文件中。我对这段代码没有任何问题,它运行良好。

    稍后,回到我的 Activity ,检测到互联网连接,我尝试恢复保存在磁盘上的文件:
    phantoms = new ArrayList<Funcionario>();
    Object obj = arq.readObjectFromFile(openFileInput("dados.jlog"));
    Funcionario func = null;
    if (obj instanceof Funcionario) {
    func = (Funcionario) obj;
    }
    while (func != null) {
    phantoms.add(func);
    arq.removeObjectFromFile(openFileInput("dados.jlog"), func,
    getApplicationContext());
    func = (Funcionario) arq
    .readObjectFromFile(openFileInput("dados.jlog"));
    }

    最初的想法是一次读取 1 个对象,然后尝试传输它,如果成功,则从文件中删除该对象(因此它不会被重新传输)。但是,我对此有太多错误消息。相反,我决定一次一个地加载所有对象,以更清楚地了解我的问题在哪里。

    返回 Arquivador类(class):
    public Object readObjectFromFile(FileInputStream arquivo) {
    Object retorno = null;
    if (arquivo.equals(null)) {
    Log.e(TAG_NAME, "FIS is null!");
    }
    ObjectInputStream ois = null;
    try {
    ois = new ObjectInputStream(arquivo);
    retorno = ois.readObject();
    } catch (IOException ioex) {
    } catch (ClassNotFoundException e) {
    } finally {
    try {
    if (ois != null) ois.close();
    } catch (IOException e) {
    }
    }
    return retorno;
    }

    public void removeObjectFromFile(FileInputStream arqPrincipal,
    Object objetoARemover, Context contexto) {
    try {
    // Construct the new file that will later be renamed to the original
    // filename.
    ObjectOutputStream oos = new ObjectOutputStream(
    contexto.openFileOutput("dados.jlog.temp",
    contexto.MODE_APPEND));
    ObjectInputStream ois = new ObjectInputStream(arqPrincipal);
    Object obj = null;
    // Read from the original file and write to the new
    // unless content matches data to be removed.
    try {
    while ((obj = ois.readObject()) != null) {
    if (!(objetoARemover.equals(obj))) {
    oos.writeObject(obj);
    oos.flush();
    }
    }
    } catch (EOFException eof) {
    } finally {
    oos.close();
    ois.close();
    // Delete the original file
    File aDeletar = contexto.getFileStreamPath("dados.jlog");
    File aRenomear = contexto.getFileStreamPath("dados.jlog.tmp");
    if (!aDeletar.delete()) {
    return;
    } else {
    // Rename the new file to the filename the original file
    // had.
    if (!aRenomear.renameTo(aDeletar)) Log.d(TAG_NAME,
    "Error renaming file");
    else Log.d(TAG_NAME, "Renaming successful");
    }
    }
    } catch (FileNotFoundException ex) {
    ex.printStackTrace();
    Log.d(TAG_NAME, "Arquivo não encontrado");
    } catch (IOException ex) {
    ex.printStackTrace();
    Log.d(TAG_NAME, "Erro de entrada/saída");
    } catch (ClassNotFoundException e) {
    Log.d(TAG_NAME, "Classe Não Encontrada.");
    }
    }

    方法 readObjectFromFile()似乎工作得很好。我什至可以将读取的对象转换为 Funcionario类并读取其数据。

    我使用 removeObjectFromFile() 时出现问题.这个想法是创建一个临时文件来存储“dados.jlog”文件中的对象,而不是已经在主程序中加载的文件,然后一旦创建了这个临时文件,应该删除文件“dados.jlog”并应重命名临时文件以替换它。

    我在这里发现的第一件事很奇怪是 ois.readobject()不断抛出EOFException。虽然这是有道理的,但我在互联网上阅读的教程并没有提到这个错误。事实上,他们的代码表明,当 readObject() 方法到达 EOF 时,它会返回对 null 的引用,但是这个类会抛出这个 EOFException。我在代码中处理了这个异常——尽管我不确定这是否是正确的方法。

    我觉得奇怪的另一件事是这段代码无法识别它不应该复制的对象。当我将从文件中读取的对象与作为参数接收的对象进行比较时,无论我尝试什么(==、equals() 等),它们对编译器来说都是不同的对象。 Funcionario 类是可序列化的,有一个 serialversionUID,所以从文件中读取的对象应该与我存储的对象相同。比这更糟糕的是,这两个被比较的对象是从同一个文件中读取的。它们应该是相同的,对吧?

    创建临时文件后,我尝试删除原始文件并重命名临时文件。虽然这似乎有效,但一旦 removeObjectFromFile() 第一次结束,程序就无法再次从文件“dados.jlog”中读取数据。我无法从文件中读取剩余的数据,程序进入无限循环 - 因为第一个对象永远不会从文件的列表中删除。

    请赐教这个问题。

    最佳答案

    我个人会使用 SQLLite 数据库。将每个对象存储在数据库中的一行中。成功传输后,您可以从数据库中删除该行。

    您甚至可以重用您已经完成的大部分代码。从您所在的位置到达那里的最简单方法是为每个对象使用单独的文件,并仅将对象的文件名存储在数据库中。然后,您可以遍历数据库中的行。每次将对象传输到服务器时,只需从数据库中删除该行(并从文件系统中删除文件!)。数据库中没有行意味着没有对象要传输。

    关于java - 如何更新由 openFileOutput 创建的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6849937/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com