В настоящее время я создаю приложение, в котором пользователь будет генерировать данные с течением времени и, если он / она имеет подключение к Интернету, передавать их в Интернет. Однако, если у него нет доступа к Интернету, мне нужно хранить эти данные в телефоне до тех пор, пока пользователь не восстановит свой доступ, когда мне нужно будет восстановить эти данные для передачи. Тем не менее, я сталкиваюсь с множеством неприятностей, чтобы сделать это, как показано ниже.
Примечание: прежде всего я использую локальный файл, созданный Java, потому что я не знаю другого способа сохранить / восстановить эти данные на устройстве. Если вам известен какой-либо другой способ хранения / доступа к этим данным из устройства, пожалуйста, не стесняйтесь комментировать здесь.
Только для справки,
- фантомы - это 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.");
}
}
Вы заметите, что я добавляю данные в постоянство в 2 этапа: первый объект и остальные. Эту идею я увидел в этом посте здесь, в StackOverflow, чтобы разрешить добавление данных в файл, сгенерированный Java. У меня нет проблем с этим кодом, он работает отлично.
Позже, вернувшись к моей Активности, обнаруживается интернет-соединение, и я пытаюсь восстановить файл, сохраненный на диске:
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
:
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, он возвращает ссылку на ноль, но вместо этого этот класс выдает это исключение EOFException. Я обработал это исключение в коде - хотя я не уверен, что это будет правильным способом.
Другая вещь, которую я нахожу странной, это то, что этот код не может распознать объект, который он НЕ должен копировать. Когда я сравниваю объект, прочитанный из файла, с объектом, полученным в качестве аргумента, независимо от того, что я пытаюсь (==, equals () и т. Д.), Они кажутся компилятору различными объектами. Класс Funcionario является сериализуемым и имеет serialversionUID, поэтому объект, считываемый из файла, должен быть идентичным тому, который я сохранил. Хуже того, эти 2 сравниваемых объекта считываются из одного и того же файла. Они должны быть одинаковыми, верно?
После создания временного файла я пытаюсь удалить исходный файл и переименовать временный файл. Хотя кажется, что это работает, после того как removeObjectFromFile () завершает работу в первый раз, программа не может снова прочитать данные из файла "dados.jlog". Я не могу прочитать оставшиеся данные из файла, и программа входит в бесконечный цикл - поскольку 1-й объект никогда не удаляется из списка в файле.
Пожалуйста, просветите меня этим вопросом.