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

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

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

仅供参考,

> phantoms是一个ArrayList,其中包含带有我需要的数据的对象

商店,

> Arquivador是我用来保持数据持久性和恢复数据的类,

> Funcionario是带有程序生成的数据的类(仅包含几个字符串和数字)

我可以通过以下代码在“活动”中将文件写入文件系统:

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中看到的on this post,可以将数据附加到Java生成的文件中的想法.我对此代码没有问题,它可以完美运行.

稍后,回到“活动”,检测到Internet连接,我尝试恢复磁盘上保存的文件:

phantoms = new ArrayList();

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类:

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数据库.将每个对象存储在数据库的一行中.成功传输后,您可以从数据库中删除该行.

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

标签:file,java,android

来源: https://codeday.me/bug/20191208/2089076.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值