2012-05-26 2 views
0

Работа с клиентским/серверным чат-приложением, позволяющим отправлять файлы (изображения/видео ...) через соединение сокета.Передача файлов и сериализация объектов в Java

Для управления всеми видами связи я использую объект «Пакет», в котором хранится вся информация, которую я хочу отправить. (Отправитель, приемники, файл ...).

Вот пример кода, где я пишу в потоке:

private void write(Packet packet) throws IOException { 
    ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
    ObjectOutputStream os = new ObjectOutputStream(bos); 
    os.writeObject(packet); 
    this.outStream.write(bos.toByteArray()); 
} 

И outStream является OutputStream.

Вот мое подключение пробег:

public void run() { 
    while (isRunning()) { 
     try { 
      byte[] buffer = new byte[65536]; 
      // Read from the InputStream 
      inStream.read(buffer); 
      ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buffer)); 
      Packet p = (Packet) in.readObject(); 

     } catch (IOException e) { 
      e.printStackTrace(); 
      this.disconnect(); 
     } 
    } 
} 

Это работает очень хорошо для всех целей, кроме передачи файлов! Я поместил файл в байт [] (с файловым потоком) и сохранил массив в моем объекте пакета. Когда сервер получает сообщение, он разбивается на «in.readObject()» и дает мне довольно «исключение java io streamcorruptedexception wrong format: 0».

Я пробовал передачу с помощью пользовательского байта [] (заполненным string.getBytes()), и он работал очень хорошо.

Итак, что я делаю неправильно?

ответ

3

Вы читаете из InputStream в массив байтов (с произвольным размером, который может быть слишком маленьким). Затем вы создаете ObjectInputStream для чтения из этого массива байтов. Почему бы вам не прочитать свой объект непосредственно из InputStream?

ObjectInputStream in = new ObjectInputStream(inStream); 
Packet p = (Packet) in.readObject(); 

Нет необходимости в буфере.

Кроме того, InputStream.read() не считывает все из InputStream. Он считывает то, что доступно, и возвращает количество прочитанных байтов. Если вы не зацикливаете до тех пор, пока не вернете -1, вы прочитаете только часть того, что было отправлено с другой стороны.

Кстати, вы делаете ту же ошибку со стороны отправки. Вместо того, чтобы записывать свой объект непосредственно в выходной поток, вы записываете его в массив байтов, а затем отправляете этот массив байтов. Напишите свой объект непосредственно в потоке:

ObjectOutputStream os = new ObjectOutputStream(this.outputStream); 
os.writeObject(packet); 

Нет необходимости в буфере.

+0

Спасибо. Прекрасно работает. Вот как выглядит мой запуск: 'ObjectInputStream in = new ObjectInputStream (inStream); while (in.read()! = -1) { } Пакет p = (Пакет) in.readObject(); ' – LukeS

+1

Вам не нужен цикл. Это необходимо, если вы читаете байты (которые вы сделали в исходном коде). Если вы читаете объект, ObjectInputSTream будет считывать столько байтов, сколько необходимо для возврата первого объекта в поток байтов. –

Смежные вопросы