我正在构建一个应用程序,用户会随着时间生成数据,并且如果他/她有互联网连接,将数据传输到网络。但是,如果他没有网络访问权限,我需要将此数据存储在手机中,直到用户恢复访问权限时,我将需要恢复此数据以进行传输。然而,我遇到了很多困难,如下所示。
注意:首先,我使用本地创建的Java文件,因为我不知道从设备内部保存/还原此数据的其他方法。如果您知道从设备内部存储/访问此数据的其他方法,请随时在此处发表评论。
仅供参考,
- phantoms是一个ArrayList,其中包含我需要存储的对象数据, - Arquivador是我用于使我的数据持久化和恢复数据的类, - Funcionario是程序生成的数据类(只有一些字符串和数字)。
我能够通过以下代码在我的Activity上将文件写入文件系统:
你会注意到我在持久化数据时分成两步,第一步是对象,剩下的则是其他内容。这个想法我在StackOverflow上看到这篇文章提到,目的是允许将数据附加到Java生成的文件中。我对这段代码没有问题,它完美地工作着。
稍后,在我的Activity中,检测到网络连接并尝试恢复保存在磁盘上的文件:
原始想法是一次读取一个对象,然后尝试传输它,如果成功,就从文件中删除该对象(以免被重新传输)。然而,我在这方面遇到了太多的错误消息。因此,我决定一次性加载所有对象,逐个查看问题所在。回到“Arquivador”类:
方法
创建临时文件后,我尝试删除原始文件并重命名临时文件。虽然这似乎有效,但一旦removeObjectFromFile()第一次结束,程序就无法再次从文件“dados.jlog”中读取数据。我无法从文件中读取剩余的数据,程序进入了一个无限循环 - 因为第一个对象从文件中的列表中永远不会被删除。
请为我解决这个问题。
注意:首先,我使用本地创建的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.");
}
}
你会注意到我在持久化数据时分成两步,第一步是对象,剩下的则是其他内容。这个想法我在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"));
}
原始想法是一次读取一个对象,然后尝试传输它,如果成功,就从文件中删除该对象(以免被重新传输)。然而,我在这方面遇到了太多的错误消息。因此,我决定一次性加载所有对象,逐个查看问题所在。回到“Arquivador”类:
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。我在代码中处理了这个异常-虽然我不确定这是否是正确的处理方式。
创建临时文件后,我尝试删除原始文件并重命名临时文件。虽然这似乎有效,但一旦removeObjectFromFile()第一次结束,程序就无法再次从文件“dados.jlog”中读取数据。我无法从文件中读取剩余的数据,程序进入了一个无限循环 - 因为第一个对象从文件中的列表中永远不会被删除。
请为我解决这个问题。
// TODO Auto-generated catch block
- 但请发布所有可能有用的代码。 - Mr_and_Mrs_D