2

サーバーサイド(Tomcat 6.0.29)でHashMapをシリアル化し、クライアント側のAndroidアプリケーションで非シリアル化しようとしています。

初めてこれを試したとき、StreamCorruptedExceptionが発生しましたが、クリーンなdoGet / doPostメソッドを使用して完全に新しいサーブレットを作成した後、この問題を解決できました。残念ながら、代わりにEOFExceptionが発生します。

したがって、最初にコードを投稿してから、問題について詳しく説明します。

サーバーサイドコード(これは、doPostまたはdoGetが呼び出されたときに実行されます):

    if ("object".equals(request.getParameter("format")))
        {

            trace.log("Before Serializing");
            ObjectOutputStream out = null;
            try
            {
                out = new ObjectOutputStream(response.getOutputStream());
                out.writeObject(outerTable);
                trace.log("after Serializing");
            }
            finally
            {
                if(out != null)
                {
                    try
                    {
                        out.flush();
                        out.close();
                    }
                    catch(Exception ex)
                    {
                        trace.log("Exception has been thrown "+ex.getMessage());
                    }
                }
            }
            trace.log("after closing stream");
        }
        else
        {
            PrintWriter out = response.getWriter();
            out.println(outerTable.toString());
        }

externalTableは、このコードブロックの直前に作成されたHashMapであり、常に正しい値を持っています。

サーバー側でスローされるエラーはありません。パラメータ「?format = object」を使用してWebブラウザのサーブレットにアクセスしようとすると、シリアル化文字列全体が取得されます。

Androidアプリケーションのスクリプト(このメソッドは、特定のボタンが押された後にhttpリクエストを実行します):

    private synchronized void performNetworkAccess()
    {
  Runnable run = new Runnable()
  {
    @Override
    public void run()
    {
    System.out.println("in run()-Method");
    ObjectInputStream objInput = null;
    try
    {
        URL url = new URL(myWebsite);
        URLConnection con = url.openConnection();
        InputStream in = con.getInputStream(); 
        objInput = new ObjectInputStream(in);

        outerTable = (HashMap<String, HashMap<String, Object>>)              objInput.readObject();
        synchronized (monitor)
        {
        monitor.notifyAll();
        }
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
    }
    finally
    {
        if (objInput != null)
        {
        try
        {
            objInput.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        }
    }

    }

};
Thread t1 = new Thread(run);
t1.start();
}

例外は、ObjectInputStreamクラスのコンストラクターが呼び出された直後に発生します。

スタックトレース:

  • W / System.err(1797):java.io.EOFException
  • W / System.err(1797):libcore.io.Streams.readFully(Streams.java:83)で
  • W / System.err(1797):java.io.DataInputStream.readShort(DataInputStream.java:169)で
  • W / System.err(1797):java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:2102)で
  • W / System.err(1797):java.io.ObjectInputStream。(ObjectInputStream.java:372)で
  • W / System.err(1797):de.tesla.jtheseuscontactsync.ContactSync $ 4.run(ContactSync.java:602)
  • W / System.err(1797):java.lang.Thread.run(Thread.java:856)で

私はすでにこの問題の多くの発生を発見しましたが、readObject()が呼び出される前にこのエラーが発生するそれらの1つを見ませんでした。

私がすでに試したこと:

  • ObjectOutputStreamを構築した直後にout.flush()を追加します
  • out.flush()および/またはout.close()メソッドを削除します
  • Input-/OutputStreamをBufferedInput-/-OutputStreamでラップします
  • ストリームをファイルとして取得し、ファイルの非現実化を試みます

奇妙なことに、最初にFileOutputStreamを介してオブジェクトをファイルに書き込み、Url.openStream()を介してクライアントからこのファイルに(サーバー上で)アクセスすると、ObjectOutputStreamはこのオブジェクトを完全に読み取ることができます。残念ながら、これは多くの問題を意味します。このオブジェクトを同時に取得しようとしている複数のユーザー...

私はあなたがこれで私を助けることができることを願っています:)

4

2 に答える 2

0

サーブレットにはある種の例外があり、ObjectOutputStreamを構築していません。クライアントでObjectInputStreamを構築する前に、200の応答コードを確認する必要があります。

于 2012-09-18T21:55:37.563 に答える
-2

いくつかのクレイジーなアイデア...Content-Lengthあなたの応答にヘッダーを追加してみてください。バイトをByteArrayOutputStreamに書き込み、サイズを測定し、ヘッダーを設定してから応答に書き込むことを意味する可能性があります...しかし、URLConnectionが接続を途中で切断している理由である可能性があります...

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObejctOutputStream oos = new ObejctOutputStream(baos);
oos.write(...);

byte[] data = baos.toByteArray();

response.setHeader("Content-Length", "" + data.length);
response.getOutputStream().write(data);

Javaシリアル化

@Robertのコメントは正しいです。Javaのシリアル化は、異なる環境間の通信を目的としたものではありません。JVMとDalvikの間で作業している場合はさらに多くなります。したがって、別のフレームワークの方が適しています(GZip [] Streamでラップする場合でも、XMLまたはJSONを使用したものが適している可能性があります)。

于 2012-09-18T13:54:25.737 に答える