2008-09-26 10 views
18

Mam następujący kod, który pokazuje błąd lub nieporozumienie z mojej strony.Wysyłanie tego samego, ale zmodyfikowanego obiektu przez ObjectOutputStream

Wysłałem tę samą listę, ale zmodyfikowaną przez obiekt ObjectOutputStream. Raz jako [0] i inne jako [1]. Ale kiedy to przeczytam, otrzymuję [0] dwa razy. Myślę, że jest to spowodowane faktem, że wysyłam ten sam obiekt i ObjectOutputStream musi je jakoś buforować.

Czy to działa tak, jak powinno, czy powinienem zgłosić błąd?

 
import java.io.*; 
import java.net.*; 
import java.util.*; 

public class OOS { 

    public static void main(String[] args) throws Exception { 
     Thread t1 = new Thread(new Runnable() { 
      public void run() { 
       try { 
        ServerSocket ss = new ServerSocket(12344); 
        Socket s= ss.accept(); 

        ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream()); 
        List same = new ArrayList(); 
        same.add(0); 
        oos.writeObject(same); 
        same.clear(); 
        same.add(1); 
        oos.writeObject(same); 

       } catch(Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
     t1.start(); 

     Socket s = new Socket("localhost", 12344); 
     ObjectInputStream ois = new ObjectInputStream(s.getInputStream()); 

     // outputs [0] as expected 
     System.out.println(ois.readObject()); 

     // outputs [0], but expected [1] 
     System.out.println(ois.readObject()); 
     System.exit(0); 
    } 
} 

Odpowiedz

24

Strumień ma wykres odniesienia, więc obiekt, który jest wysyłany dwa razy, nie da dwóch obiektów na drugim końcu, dostaniesz tylko jeden. Przesłanie tego samego obiektu dwa razy osobno da ci to samo wystąpienie dwa razy (każde z tymi samymi danymi - co widzisz).

Zobacz metodę reset(), jeśli chcesz zresetować wykres.

-3

Co prawdopodobnie chcesz to:

ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream()); 
List same = new ArrayList(); 
same.add(0); 
oos.writeObject(same); 
oos.flush(); // flush the stream here 
same.clear(); 
same.add(1); 
oos.writeObject(same); 

przeciwnym razie ten sam obiekt będzie przepłukać dwukrotnie, gdy strumień jest zamknięty lub jego bufor zabraknie.

Po prostu FYI, gdy deserializować obiekty w, powiedzmy o1 i o2, o1 != o2.

+0

Nie, to nie rozwiązało, Max miał rację, używaj resetowania() – Pyrolistical

+0

To nie działa. 'flush()' nie ma przypisanych tutaj magicznych właściwości. – EJP

6

Max jest poprawna, ale można również użyć:

public void writeUnshared(Object obj); 

Zobacz komentarz poniżej zastrzeżenie

+2

To zadziała w tym przypadku, ale generalnie spowoduje naprawdę nieparzyste błędy. Każdy napisany obiekt komponentu będzie nadal udostępniany. Na przykład, jeśli powyższa lista została opakowana w Collections.synchronizedList, problem pozostałby. writeUnshared nie jest zbyt użyteczny. –

0

The ObjectOutputStream buforuje przypadkach, że wysyła na drucie (niekoniecznie najlepszy projekt tbh). Ale w każdym przypadku musisz zresetować strumienie wyjściowe pomiędzy wywołaniami, jeśli planujesz użyć go do (ponownego) wysłania tej samej instancji obiektu.

public void reset() throws IOException 

Reset spowoduje zignorowanie stanu wszystkich obiektów zapisanych w strumieniu. Stan zostanie zresetowany tak, aby był taki sam jak nowy ObjectOutputStream. Aktualny punkt w strumieniu jest oznaczony jako reset, więc odpowiedni ObjectInputStream zostanie zresetowany w tym samym punkcie. Obiekty uprzednio zapisane w strumieniu nie będą już nazywane jako już znajdujące się w strumieniu. Zostaną ponownie zapisane w strumieniu.

+0

Jest to jedyny możliwy projekt, biorąc pod uwagę cel projektu zachowania wykresów obiektów. – EJP

+0

Plagiat z [tutaj] (https://stackoverflow.com/a/8956926/207421). – EJP

Powiązane problemy