#java #image #io #bytearray
#java #изображение #io #массивы
Вопрос:
Я пытаюсь получить изображение, закодированное в массиве байтов.
Это хорошо работает, если изображение не слишком большое, но когда мне приходится много раз читать входной поток, чтобы получить все байты изображения, строка:
BufferedImage img = ImageIO.read(new ByteArrayInputStream(finalData));
ВОЗВРАТ null
.
Вот мой код:
byte[]imgSize = new byte[SIZE_OF_LENGTH_ARRAY];
bis.read(imgSize, 0, SIZE_OF_LENGTH_ARRAY);
ByteBuffer bb = ByteBuffer.wrap(imgSize);
int size = bb.getInt();
System.out.println("Client: size=" size);
byte[] tmpData = new byte[size];
System.out.println("tmpData length = " tmpData.length);
int readen = bis.read(tmpData, 0, tmpData.length);
System.out.println("readen=" readen);
byte[]finalData = new byte[size];
if(readen == size){
finalData = tmpData;
}
else{
int totalRead = readen;
int j=1;
while(totalRead<size){
System.out.println("-----------append number " j "----------");
System.out.println("totalRead=" totalRead);
for(int i=0;i<tmpData.length;i ){
finalData[i]=tmpData[i];
}
tmpData = new byte[size-totalRead];
int tmpRead = bis.read(tmpData, 0, size-totalRead);
System.out.println("tmpRead=" tmpRead);
for(int i=0;i<tmpData.length;i ){
finalData[i totalRead]=tmpData[i];
}
totalRead =tmpRead;
j ;
}
System.out.println("totalRead final=" totalRead);
}
BufferedImage img = ImageIO.read(new ByteArrayInputStream(finalData));
И примером вывода является:
---Client: sending mess number 1---
Client: size=31099
tmpData length = 31099
readen=31099
---Client: sending mess number 2---
Client: size=85921
tmpData length = 85921
readen=17520
-----------append number 1----------
totalRead=17520
tmpRead=17520
-----------append number 2----------
totalRead=35040
tmpRead=17520
-----------append number 3----------
totalRead=52560
tmpRead=31408
-----------append number 4----------
totalRead=83968
tmpRead=1953
totalRead final=85921
image null
Хотя я хорошо прочитал 85921 байт, ImageIO.Read
получается нулевое изображение.
Ответ №1:
Эта строка может перезаписывать байты из предыдущей итерации while:
while(totalRead<size){
System.out.println("-----------append number " j "----------");
System.out.println("totalRead=" totalRead);
//I suspect this is unnecessary and one source of the error
//this loop would overwrite data from the last iteration's tmpData
for(int i=0;i<tmpData.length;i ){
finalData[i]=tmpData[i];
}
tmpData = new byte[size-totalRead];
int tmpRead = bis.read(tmpData, 0, size-totalRead);
System.out.println("tmpRead=" tmpRead);
for(int i=0;i<tmpData.length;i ){
finalData[i totalRead]=tmpData[i]; //append tmpData
}
totalRead =tmpRead;
j ;
}
Предположим, вы читаете по 10 байт в каждой итерации while.
В первом запуске вы бы установили все элементы конечных данных равными 0, затем прочитали 10 байт и установили элементы 0-9 FinalData.
На второй итерации теперь вы перебираете содержимое tmpData (которое составляет байты 0-9) и перезаписываете байты 0-9, прежде чем читать байты 10-19 и добавлять их. (пока все хорошо)
На третьей итерации вы перемещаете содержимое tmpData (которое теперь составляет 10-19 байт со второй итерации) и перезаписываете байты 0-9 в FinalData. Итак, вот одна ошибка.
Комментарии:
1. да, это именно так… Слишком поспешно, я это пропустил. Просто поместите эту итерацию перед while, и все сработает как по маслу. Спасибо.
2. Это по-прежнему не отвечает на вопрос, почему вы считываете данные в массив байтов, а затем создаете ByteArrayInputStream в качестве аргумента ImageIO.read. Просто передайте исходный поток в ImageIO.read. Он будет считывать данные за вас.
Ответ №2:
Я не знаю, что такое bis, но эта строка, вероятно, неверна:
bis.read(imgSize, 0, SIZE_OF_LENGTH_ARRAY);
Вы всегда должны проверять возвращаемое значение при чтении. При чтении может быть прочитано меньше, чем вы указали.
Редактировать:
Обычно таким образом вы считываете все данные из потока:
byte[] buffer = new byte[1024 * 32];
int len = 0;
while ((len = in.read(buffer)) > -1) {
out.write(buffer, 0, len);
}
Правка 2:
Но почему вы не делаете что-то вроде:
ImageIO.read(bis);
Комментарии:
1. извините, я забыл эту строку: bis = новый BufferedInputStream (socket.getInputStream());
2. ну, в настоящее время у меня есть только мое изображение в моем bytearray, но в следующий раз у меня будет другая информация в этом же массиве. Вот почему я извлекаю байты, относящиеся к изображению.