Пытаюсь загрузить фрагментами

#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байт