2011-07-27 15 views
3

私は現在、ユーザーが時間の経過とともにデータを生成するアプリケーションを構築しており、インターネットに接続している場合はWebに送信します。ただし、ウェブにアクセスできない場合は、ユーザーがアクセスを回復するまでこのデータを電話に保存しておく必要があります。このデータを回復する必要がある場合、送信する必要があります。しかし、私はこれを行うには以下のように多くの問題に直面しています。openFileOutputで作成されたファイルを更新するには

注:私はローカルのJavaで作成したファイルを使用していますが、このデータをデバイスに保存/復元する方法は他にありません。デバイス内からこのデータを保存/アクセスする他の方法を知った場合は、ここでコメントしてください。ただ、参考のために、

  • ファントムは
  • 、私は 店に必要なデータを持つオブジェクトを格納するArrayListあるArquivadorは、私は私のデータを永続化すると、それを回復するために使用しているクラスです。 、
  • Funcionarioは

プログラム(ほんの数文字列や数値)によって生成されたデータを持つクラスである私は、ファイルSYにファイルを書き込むことができています私の活動に以下のコードを介して、ステム:ここ

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のon this postが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つのオブジェクトを読み取ることでしたそれを送信し、成功した場合はファイルからオブジェクトを消去します(再送信されません)。しかし、私はこれであまりにも多くのエラーメッセージを持っていました。代わりに、すべてのオブジェクトを1つずつロードして、問題がより明確になっているかどうかを確認することにしました。うまく動作しているようreadObjectFromFile()

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."); 
    } 
} 

方法:バックArquivadorクラスへ

。私は読み取ったオブジェクトをFuncionarioクラスに変換し、そのデータを読むことさえできます。

removeObjectFromFile()を使用すると問題が発生します。このアイデアは、メインプログラムに既にロードされているファイル以外の "dados.jlog"ファイルからオブジェクトを保存する一時ファイルを作成し、この一時ファイルが作成されると "dados.jlog"を削除する必要があります。一時ファイルの名前を変更して置き換える必要があります。

私が最初に奇妙なことを発見したのは、ois.readobject()がEOFExceptionをスローし続けていることです。これは理にかなっていますが、私がインターネットで読んだチュートリアルでは、このエラーは言及していません。実際、そのコードは、readObject()メソッドがEOFに達するとnullへの参照を返しますが、代わりにこのクラスがこのEOFExceptionをスローすることを示しています。コード内でこの例外を処理しましたが、これが正しい方法であるかどうかはわかりませんが。

私が奇妙に感じるもう一つの事実は、このコードがコピーしてはならないオブジェクトを認識できないという事実です。ファイルから読み込んだオブジェクトを引数として受け取ったものと比較すると、何を試しても(==、equals()など)、コンパイラにとっては違うオブジェクトに見えます。 FuncionarioクラスはserializableUIDを持つ直列化可能であるため、ファイルから読み取られるオブジェクトは、格納されたものと同じでなければなりません。それよりも悪いことに、比較されるこれら2つのオブジェクトは同じファイルから読み込まれます。彼らは同じでなければなりません、そうですか?

一時ファイルを作成した後、元のファイルを削除して、一時ファイルの名前を変更しようとします。これは動作しているようですが、removeObjectFromFile()が初めて終了すると、プログラムは "dados.jlog"ファイルからデータを再度読み取ることができません。ファイルから残りのデータを読み取ることができず、プログラムは無限ループに入ります。最初のオブジェクトはファイル内のリストから削除されないためです。

この問題について私に教えてください。

+0

あなたのクラスはスペイン語以外のスピーカーにどのようなものなのかを説明していますが、英語の名前を使用してください。また、 '/ TODO自動生成キャッチブロック'のような無関係なコードを投稿しないようにしてください。しかし、便利かもしれないすべてのコードを投稿してください。 –

答えて

3

個人的には、SQLLiteデータベースを使用します。各オブジェクトをデータベースの行に格納します。送信が完了すると、データベースから行を削除できます。

既に行ったコードのほとんどを再利用することもできます。あなたがどこから来るのが最も簡単な方法は、オブジェクトごとに別々のファイルを使用し、データベースのオブジェクトのファイル名だけを格納することです。その後、データベース内の行を反復処理できます。オブジェクトをサーバーに送信するたびに、データベースからその行を削除するだけです(ファイルシステムからファイルを削除してください)。データベースに行がないということは、送信されるオブジェクトが残っていないことを意味します。

+0

WOW Man、Androidに埋め込まれたDBがあることさえ知りませんでした!私はいくつかの研究をして、それをどのように扱うかを調べます。 –

+0

このSQLLiteにはスペース制限がありますか? –

+0

私の知る限り、デバイスのスペースに限ります。うまくいけばそれは問題にならないでしょう! – Jason

関連する問題