Чтение байтового массива C # в Java - PullRequest
5 голосов
/ 18 января 2012

Я передаю файл с клиента C # на сервер Java с помощью сокетов TCP. На клиенте C # я преобразовываю файл в байтовый массив для передачи и отправляю его с помощью NetworkStream.

На сервере Java я использую следующий код для преобразования полученного байтового массива обратно в файл;

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();

        }
}

Приведенный выше код работает, если полученный байтовый массив поступает от клиента, запрограммированного на Java, но для клиентов C # код висит в цикле do-while в методе bytesRead = input.read (...).

Кто-нибудь знает, почему в данный момент код висит для клиента C #, а не клиента Java? Согласно выводу из сообщения println данные определенно принимаются InputStream и считываются один раз при инициализации переменной bytesRead, но не во время цикла do-while.

Любые решения или предложения по преодолению этой проблемы приветствуются.

С уважением,

Midavi.

Ответы [ 3 ]

1 голос
/ 18 января 2012

Вам необходимо отправить свои байты как sbyte из c # вместо byte.

Кроме того, вы должны изменить свой цикл do / while на обычный цикл while.Если вы уже прочитали все данные из потока при первом вызове на input.read, тогда вы заблокируете второй вызов, потому что read будет ожидать ввода.

0 голосов
/ 18 января 2012

Поскольку вы не можете знать объем данных, отправляемых заранее, в общем случае, было бы лучше получать данные порциями и игнорировать смещение в вашем большом массиве. Ваш код как есть не очень хорошо справляется со случаем, если данные больше, чем ваш массив, или если он меньше, чем массив.

Гораздо проще было бы удалить смещение currentByte:

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();

И я использовал следующий код C # на стороне клиента:

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());
}

Результаты на стороне клиента:

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>

Результаты на стороне сервера:

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>
0 голосов
/ 18 января 2012

На основании: http://docs.oracle.com/javase/1.4.2/docs/api/java/io/InputStream.html

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

Считывает все доступные байты, что означает, что ваши байтовые данные считываются в byteArrayJAR или я здесь совершенно не прав?

EDIT:

Только что проверил некоторые из моих проектов ... Я отправляю данные из Android <=> Серверного приложения C #.

Я использую String data = input.readLine(); (Java) и _sw.WriteLine("Testdata"); (C #)

...