Чтение двоичных данных из сокета - PullRequest
3 голосов
/ 07 ноября 2010

Я пытаюсь подключиться к серверу, а затем отправить ему HTTP-запрос (в данном случае GET). Идея состоит в том, чтобы запросить файл, а затем получить его с сервера.

Должен работать как с текстовыми, так и с двоичными файлами (например, imgs). У меня нет проблем с текстовыми файлами, они отлично работают, но у меня проблемы с двоичными файлами.

Сначала я объявляю BufferedReader (для чтения заголовка и текстового файла) и DataInput Stream:

BufferedReader in_text = new BufferedReader(
    new InputStreamReader(socket.getInputStream()));

DataInputStream in_binary = new DataInputStream(
    new BufferedInputStream(socket.getInputStream()));

Затем я читаю заголовок с помощью in_text и выясняю, является ли это текстовым или двоичным файлом. Если это текстовый файл, я правильно его прочитал в StringBuilder. В случае, если это двоичный файл, я объявляю байт [размер файла] и сохраняю следующее содержимое in_binary.

byte[] bindata = new byte[filesize];
in_binary.readFully(bindata);

И это не работает. Я получаю EOFException.

Я подумал, что, возможно, in_binary все еще находится на первой позиции потока, поэтому он еще не прочитал заголовок. Поэтому я зафиксировал длину заголовка и пропустил эти байты в in_binary.

byte[] bindata = new byte[filesize];
in_binary.reset();
in_binary.skip(headersize);
in_binary.readFully(bindata);

И все тот же.

Что может происходить?

Спасибо!

PD: я знаю, что могу использовать URLConnection и все такое. Это не проблема.

Ответы [ 2 ]

3 голосов
/ 07 ноября 2010

BufferedReader буферизует данные (отсюда и имя) - он почти наверняка будет читать больше данных из сокета, чем просто заголовок.Поэтому, когда вы пытаетесь прочитать фактические данные, некоторые из них уже были прочитаны из сокета.Если вы попробуете прочитать всего несколько байтов, вы, вероятно, увидите, что они не являются первыми байтами фактических данных ответа.

Если вы знаете, как использовать URLConnection, я должен спросить себя, почемуне использовать его.

1 голос
/ 07 ноября 2010

Как только вы используете какой-либо подкласс Reader, вы не читаете двоичный файл. Вы конвертируете из байтов в символы, используя кодировку JVM по умолчанию. Если вам действительно нужны двоичные байты, вам нужно придерживаться потоков, а не читателей. Создание обоих стеков одновременно создает проблемы.

Используйте Apache Commons IO: IOUtils.toByteArray () для чтения всего содержимого в память в виде байта [], а затем решите, что делать с ним, если только у вас нет гигантского объема данных, в этом случае вам следует установить вверх по буферизованному входному потоку, решите, что делать, и создайте считыватель только после того, как вы вернетесь назад.

...