Java 如何更新由openFileOutput创建的文件
我目前正在构建一个应用程序,用户将随着时间的推移生成数据,如果他/她有互联网连接,将数据传输到web。但是,如果他没有网络访问权限,我需要将这些数据存储在手机中,直到用户恢复访问权限,此时我需要恢复要传输的数据。然而,我面临着很多麻烦,要做到这一点,如下所示 注意:首先,我使用本地java创建的文件,因为我不知道在设备上保存/恢复这些数据的其他方法。如果您碰巧知道从设备中存储/访问此数据的任何其他方法,请随时在此发表评论 仅供参考Java 如何更新由openFileOutput创建的文件,java,android,file,Java,Android,File,我目前正在构建一个应用程序,用户将随着时间的推移生成数据,如果他/她有互联网连接,将数据传输到web。但是,如果他没有网络访问权限,我需要将这些数据存储在手机中,直到用户恢复访问权限,此时我需要恢复要传输的数据。然而,我面临着很多麻烦,要做到这一点,如下所示 注意:首先,我使用本地java创建的文件,因为我不知道在设备上保存/恢复这些数据的其他方法。如果您碰巧知道从设备中存储/访问此数据的任何其他方法,请随时在此发表评论 仅供参考 phantoms是一个ArrayList,其中包含我需要的数据
- phantoms是一个ArrayList,其中包含我需要的数据对象 商店
- Arquivador是我用来使数据持久化和恢复数据的类
- Functionario是包含程序生成的数据的类(只有几个字符串和数字)
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生成的文件中。我对这个代码没有问题,它工作得很好
稍后,在我的活动中,检测到internet连接,我尝试恢复保存在磁盘上的文件:
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"));
}
方法readObjectFromFile()
似乎工作正常。我甚至可以将read对象转换为Funcionario
类并读取其数据
使用removeObjectFromFile()
时会出现问题。其想法是创建一个临时文件来存储“dados.jlog”文件中的对象,而不是主程序中已加载的文件,然后创建此临时文件后,应删除文件“dados.jlog”,并重命名临时文件以替换它
我在这里发现的第一件奇怪的事情是,ois.readobject()
不断抛出一个EOFEException。虽然这是有道理的,但我在互联网上阅读的教程没有提到这个错误。事实上,他们的代码表明,当readObject()方法到达EOF时,它将返回对null的引用,但该类会抛出此EOFEException。我在代码中处理了这个异常——尽管我不确定这样做是否正确
另一件我觉得奇怪的事情是,这段代码无法识别它不应该复制的对象。当我将从文件中读取的对象与作为参数接收的对象进行比较时,无论我尝试(=,equals(),等等),它们在编译器看来都是不同的对象。Functionario类是可序列化的,它有一个serialversionUID,因此从文件中读取的对象应该与我存储的对象相同。更糟糕的是,这两个被比较的对象是从同一个文件中读取的。它们应该是一样的,对吗
创建临时文件后,我尝试删除原始文件并重命名临时文件。尽管这似乎是可行的,但一旦removeObjectFromFile()第一次结束,程序将无法再次从文件“dados.jlog”中读取数据。我无法从文件中读取剩余的数据,程序进入一个无休止的循环-因为第一个对象从未从文件列表中删除
请告诉我这件事。我个人会使用SQLLite数据库。将每个对象存储在数据库中的一行中。成功传输后,可以从数据库中删除该行
您甚至可以重用已经完成的大部分代码。最简单的方法是为每个对象使用单独的文件,并在数据库中只存储对象的文件名。然后可以在数据库中的行上进行迭代。每次将对象传输到服务器时,只需从数据库中删除该行(并从文件系统中删除该文件!)。数据库中没有行意味着没有对象可以传输。哇,我甚至不知道Android中有嵌入式数据库!我会做一些研究来找出如何使用它。只是想知道,这个SQLLite有没有空间限制?据我所知,它只限于设备上的空间。希望这不会成为问题!虽然你向非西班牙语的人解释了你的课程,但仍然很难理解-请使用英语名称。另外,尽量不要发布不相关的代码,比如
//TODO自动生成的catch block
——而是发布所有可能有用的代码
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.");
}
}