2012-01-18 12 views
5

Przenoszę plik z klienta C# do serwera Java za pomocą gniazd TCP. Na kliencie C# konwertuję plik na tablicę bajtów w celu przesłania i wysyłam go za pomocą NetworkStream.Odczytywanie tablicy bajtów C# w Javie

Na serwerze Java używam następującego kodu do konwersji odebranej tablicy bajtów z powrotem do pliku;

public void run() { 

     try { 

      byte[] byteArrayJAR = new byte[filesize]; 
      InputStream input = socket.getInputStream(); 

      FileOutputStream fos = new FileOutputStream(
        "Controller " + controllerNumber + ".jar"); 

      BufferedOutputStream output = new BufferedOutputStream(fos); 

      int bytesRead = input.read(byteArrayJAR, 0, byteArrayJAR.length); 
      int currentByte = bytesRead; 

      System.out.println("BytesRead = " + bytesRead); 

      do { 

       bytesRead = input.read(
         byteArrayJAR, 
         currentByte, 
         (byteArrayJAR.length - currentByte)); 

       if (bytesRead >= 0) { 

        currentByte += bytesRead; 

       } 
      } 

      while (bytesRead > -1); 

      output.write(byteArrayJAR, 0, currentByte); 
      output.flush(); 
      output.close(); 
      socket.close(); 

     } 

     catch (IOException e) { 

      e.printStackTrace(); 

     } 
} 

Powyższy kod działa, jeśli odebrany bajt array pochodzi od klienta zaprogramowanego z Java, ale dla klientów C# kod wisi w do-while metoda pętla na bytesRead = input.read (...).

Czy ktoś wie, dlaczego kod jest zawieszony w tym momencie dla klienta C#, ale nie dla klienta Java? Zgodnie z danymi wyjściowymi z komunikatu println dane są odbierane przez InputStream i są odczytywane raz podczas inicjalizacji zmiennej bytesRead, ale nie podczas pętli do-while.

Wszelkie rozwiązania lub sugestie dotyczące rozwiązania tego problemu byłyby mile widziane.

Pozdrawiam,

Midavi.

+2

Pokaż nam swój kod C#. Czy może brakuje Ci 'Flush()'? – dtb

+3

Jeśli rozmiar pliku nie jest mniejszy lub równy skutecznie przesyłanym danym, funkcja read() zostanie zablokowana. Nigdy nie powinieneś próbować odgadnąć rozmiaru danych, które otrzymasz, musisz czytać, dopóki strumień nie będzie pusty. – Viruzzo

Odpowiedz

0

podstawie: http://docs.oracle.com/javase/1.4.2/docs/api/java/io/InputStream.html

int bytesRead = input.read(byteArrayJAR, 0, byteArrayJAR.length); 

Czyta wszystkie dostępne bajty oznacza, że ​​bajt danych jest alread w byteArrayJAR czy jestem zupełnie niewłaściwy tutaj?

EDIT:

Tylko sprawdzone niektóre z moich projektów ... mogę wysłać dane z Androida < => C# Application Server.

używam String data = input.readLine(); (Java) i _sw.WriteLine("Testdata"); (C#)

+0

Tak też uważam. O ile wiem, jeśli wysyłany plik jest dość duży, więcej bajtów może stać się dostępnych po zainicjowaniu bajtrei. Pętla do-while służy do sprawdzania, czy cała tablica bajtów jest czytana przed odtworzeniem w pliku. Czy mam to źle? – midavi

1

Musisz wysłać bajtów jako sbyte z C zamiast # byte.

Ponadto należy zmienić pętlę do/while na zwykłą pętlę. Jeśli przeczytałeś już wszystko ze strumienia w swoim pierwszym połączeniu z numerem input.read, zablokujesz drugie połączenie, ponieważ read będzie czekać na dane wejściowe.

+0

To nie powinno powodować zawieszenia, ale może być problem w pewnym momencie. – user7116

+0

, dopóki nie rozwiążesz tego problemu, nie będziesz w stanie niezawodnie rozwiązać innych problemów z powodu błędnych danych binarnych. –

+0

Podpisany bajt ma taką samą szerokość jak bajt bez znaku, dlatego różnica w reprezentacji nie wpłynie na odczyt z gniazda. Obecny problem OP * leży gdzie indziej. – user7116

0

Ponieważ nie można znać ilości danych wysyłanych z wyprzedzeniem w ogólnym przypadku, lepiej byłoby otrzymać dane w porcjach i zignorować przesunięcie w większej macierzy. Twój kod jak-i nie radzi sobie z sytuacją bardzo dobrze, jeśli dane są większe niż twoja tablica, lub jeśli jest mniejsza niż tablica.

znacznie prostszy przypadek byłoby usunąć currentByte offset:

InputStream input = socket.getInputStream(); 
BufferedOutputStream output = new BufferedOutputStream(
    new FileOutputStream("test.exe")); 

byte[] bytes = new byte[2048]; 
int bytesRead; 
do { 
    bytesRead = input.read(bytes, 0, bytes.length); 
    System.out.println("size: " + bytes.length + " read(): " + bytesRead); 

    if (bytesRead > 0) { 
     output.write(bytes, 0, bytesRead); 
    } 
} while (bytesRead > -1); 

output.close(); 
socket.close(); 
input.close(); 

I używany następujący kod C# po stronie klienta:

if (!args.Any()) 
{ 
    Console.Error.WriteLine("Usage: send.exe <executable>"); 
    Environment.Exit(-1); 
} 

using (var client = new TcpClient("localhost", 10101)) 
using (var file = File.Open(args.First(), FileMode.Open, FileAccess.Read)) 
{ 
    file.CopyTo(client.GetStream()); 
} 

wyników boczne Klient:

C:\temp>csc send.cs 
Microsoft (R) Visual C# 2010 Compiler version 4.0.30319.1 
Copyright (C) Microsoft Corporation. All rights reserved. 


C:\temp>send send.exe 

C:\temp> 

Wyniki po stronie serwera:

C:\temp>javac.exe Server.java 

C:\temp>java Server 
size: 2048 read(): 2048 
size: 2048 read(): 2048 
size: 2048 read(): 512 
size: 2048 read(): -1 

C:\temp>test.exe 
Usage: send.exe <executable> 
Powiązane problemy