#java #blackberry #java-me #https #multipartform-data
#java #ежевика #java-me #https #составная форма-данные
Вопрос:
Я пытаюсь выполнить загрузку большого файла на blackberry. Я успешно могу загрузить файл, но только если я прочитаю файл и загружу его по 1 байту за раз. Я думаю, что для больших файлов это снижает производительность. Я хочу иметь возможность читать и записывать что-то более 128 КБ за раз. Если я попытаюсь инициализировать свой буфер чем-либо иным, кроме 1, то я никогда не получу ответ от сервера после записи всего.
Есть идеи, почему я могу загружать, используя только 1 байт за раз?
z.write(boundaryMessage.toString().getBytes());
DataInputStream fileIn = fc.openDataInputStream();
boolean isCancel = false;
byte[]b = new byte[1];
int num = 0;
int left = buffer;
while((fileIn.read(b)>-1))
{
num = b.length;
left = buffer - num * 1;
Log.info(num "WRITTEN");
if (isCancel == true)
{
break;
}
z.write(b);
}
z.write(endBoundary.toString().getBytes());
Комментарии:
1. Почему вы используете DataInputStream? Возникает ли эта проблема, если вы используете openInputStream() и правильно подсчитываете байты, как предложено в некоторых ответах?
2. Какое устройство и ОС вы используете? Пожалуйста, также добавьте остальной код, который вы используете, чтобы было показано, как вы открываете / обрабатываете / закрываете HttpConnection.
Ответ №1:
Это ошибка в BlackBerry OS, которая появилась в OS 5.0 и сохраняется в OS 6.0. Если вы попытаетесь использовать многобайтовое чтение до OS 5, оно будет работать нормально. OS5 и более поздние версии ведут себя так, как вы описали.
Вы также можете обойти проблему, создав безопасное соединение, поскольку ошибка проявляется не для защищенных сокетов, а только для обычных сокетов.
Ответ №2:
Большинство входных потоков не гарантированно заполняют буфер при каждом чтении. ( DataInputStream
для этого есть специальный метод, readFully(), который выдает сообщение EOFException
, если в потоке осталось недостаточно байтов для заполнения буфера.) И если файл не кратен длине буфера, ни один поток не заполнит буфер при окончательном чтении. Итак, вам нужно сохранить количество прочитанных байтов и использовать его во время записи:
while(!isCancel)
{
int n = fileIn.read(b);
if (n < 0)
break;
num = n;
Log.info(num "WRITTEN");
z.write(b, 0, n);
}
Комментарии:
1. Привет, Эриксон, просто попробуйте, но безуспешно, клиент / сервер, похоже, просто не завершает соединение после записи всех байтов, как это происходит, когда я записываю по 1 байту за раз.
2. когда я анализирую wireshark с использованием вашего кода, кажется, что при размере файла 119 кб передается всего 9542байт.
3. Также пробовал этот цикл, но зависает, когда я печатаю endboundary и пытаюсь открыть inputstream для чтения ответа, а в tcp-диалоге wireshrk находится 9542байт.
4. все еще пытаюсь — не могу понять, почему все пройдет нормально, если я напечатаю байты изображения по одному, но если я напечатаю их как 1024 * 8, то я не получу ответ от сервера.
Ответ №3:
Ваш цикл неверен. Вы должны позаботиться о возвращаемом значении из read. Возвращает, сколько байтов было фактически прочитано, и это не всегда совпадает с размером буфера.
Редактировать: Обычно вы так пишете циклы, которые выполняют то, что вы хотите сделать:
OutputStream z = null; //Shouldn't be null
InputStream in = null; //Shouldn't be null
byte[] buffer = new byte[1024 * 32];
int len = 0;
while ((len = in.read(buffer)) > -1) {
z.write(buffer, 0, len);
}
Обратите внимание, что вы можете захотеть использовать буферизованные потоки вместо небуферизованных потоков.
Комментарии:
1. Также пробовал этот цикл, но зависает, когда я печатаю endboundary и пытаюсь открыть inputstream для чтения ответа, и в tcp-диалоге wireshrk находится 9542байт