Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java ME (J2ME) > Получение файла из потока


Автор: vandaler 27.11.2009, 23:28
Задача - принять строку от сервера, в которой хранится файл, где 5 первых символов - длина строчки с самим файлом, а дальше файл.
Код

             int size = 0;
             for (i=0; i<5; i++)
             {
                size = size*10 + is.read() - 48;
             }             
             byte[] im = null;
             int c;
             i  = is.read(im, 0, size);

такой код виснет на последней строке. однако если считывать сообщение побайтно - все работает. помогите, в чем беда?

Автор: W0LF 28.11.2009, 15:03
ничего не понял, если честно, но проблема сокрее всего здесь - 
Код

size = size*10 + is.read() - 48;

мне кажется у тебя слишком большой size получается, и соответственно в потоке нет столько байт.
но это если виснет. а вообще по идее вылетать должно.
у тебя im должен быть инициализирован и под него уже должна быть выделена память, а он null, соответственно я бы твое зависание назвал ексепшином.
доки читать надо!
Цитата

public int read(byte[] b,
                int off,
                int len)
         throws IOException

    Reads up to len bytes of data from the input stream into an array of bytes. An attempt is made to read as many as len bytes, but a smaller number may be read, possibly zero. The number of bytes actually read is returned as an integer.

    This method blocks until input data is available, end of file is detected, or an exception is thrown.

    If b is null, a NullPointerException is thrown.

    If off is negative, or len is negative, or off+len is greater than the length of the array b, then an IndexOutOfBoundsException is thrown. 

Автор: vandaler 28.11.2009, 20:43
точно! спасибо. надо было инициализировать массив.
а вот я получил маччив байт im. мне нужно получить из него картнку. Image.createImage(im, 0, size) выдает исключение IllegalArgument. как правильно?  

Автор: W0LF 29.11.2009, 00:53
вот http://java.sun.com/javame/reference/apis/jsr118/ находится документация по MIDP, так же она есть локально при установке WTK.
и в этой самой документации сказно - 
Цитата

IllegalArgumentException - if imageData is incorrectly formatted or otherwise cannot be decoded

IllegalArgumentException, если данные картинки имеют неправильный формат или же не могут быть декодированы

Автор: vandaler 29.11.2009, 01:08
ага, разобрался. чтение файла из потока блоком оказалось ненадежным. картинка иногда приходит не вся. поэтому, наверное, надо в конец файла добавить какую-то уникальную полследовательность символов, и счиывать до нее. или есть лучшие способы? 

Автор: W0LF 30.11.2009, 04:59
нет, если не использовать udp то картинка должна приходить полностью, есть так называемые тобой блоки, которые разрешают вычитать все доступные на данный момент данный из потока, но это не значит что картинка тебе пришла сразу вся, тебе нужно делать while пока ты не вычитаешь все данные, то есть так бы ты вычитывал по одному байту, что есть намного дольше, а так ты вычитываешь просто блоками, и поэтому тебе нужен внешний цикл, который проверит, все ли пришло.
я понимаю что вопросы будут и на эту тему, так что примерно так - 
Код

int size = is.available();//это вычитает количество доступных байт в текущем блоке
while (size > 0) {
  byte[] im = new byte[size];
  i  = is.read(im, 0, size);
  //делаем чето с нашим im, например добавляем в какой-нидь буффер
  size = is.available();
}

Автор: Dancer 1.12.2009, 13:31

  size = is.available(); - это может вернуть 0, но это не будет означать, что мы всё уже приняли. Нельзя по этой вещи организовывать цикл.
лучше смотреть на количество прочитанных байт
  i  = is.read(im, 0, size); - как i у нас станет "-1", это и будет означать, что более уже читать нечего, и можно закругляться.
А когда is.avaliable() возвращает 0, то можно вычитывать по 1 байту, пока не будет достаточно байт, для того чтобы считать их пачкой в массив.

Автор: vandaler 1.12.2009, 17:03
-1 будет тогда разорвется соединение. правильно?

Автор: Dancer 2.12.2009, 13:48
да, при закрытии коннекшена будет -1.  Или эксепшен, при разрыве соединения.

Код

....
int sizeOfFile;
....
//sizeOfFile чему-то здесь у нас уже равен

ByteArrayOutputStream bufferedStream = new ByteArrayOutputStream ();
int size = 0;
try {
    while(true) {
         int readBytes = is.available();
         if(readBytes == 0) {
             readBytes=1;
         }

         byte[] buf = new byte[readBytes];
         int needRead =0;
         if((size + readBytes) > sizeOfFile) {
             needRead = sizeOfFile - size;
         } else {
             needRead = readBytes;
         }

         int len = is.read(buf, 0, needRead);
         if(len == -1)
             break;

          bufferedStream.write(buf, 0, len);
          size += len;
          if(size == sizeOfFile) 
              break;
    }
} catch(Throwable t) { // точно не помню чего ловим.....
    System.out.println("ERROR: " + t.toString());
}

bufferedStream.flush();
byte[] im = bufferedStream.toByteArray(); // здесь получили наш массив байт.
bufferedStream.close();
bufferedStream = null;
......

Автор: W0LF 2.12.2009, 20:29
а я всегда порциями читал
и все было нормально, и быстрее
Не, с тобой, Dancer, я никоим образом спорить не буду =)
просто в j2se это точно всегда нормально работает, а в j2me не знаю...

Автор: vandaler 2.12.2009, 20:49
Dancer, так в том и дело, что у меня сокет не разрывается. когда он разрывался, я просто использовал createImage(InputStream).
А так разобрался. Благо размер файла не превышает 11 кб, сделал побайтовое чтение для надежности. На скорости не отразилось. Спасибо всем за помощь

Автор: Dancer 3.12.2009, 11:18
vandaler,  ну, да, мой косяк, я когда сначала написал, не особо посмотрел, на твой первый пост.
Но вот код, который привёл, он уже с учётом твоей специфики. (то есть, сокет не закрывается и мы знаем сколько байт нам нужно вычитать. по возможности читаем "куском", если нет, то побайтово)

         if(len == -1)   - это на всякий так сказать случай, типа а вдруг.
            break;

         if(size == sizeOfFile)  - а вот это уже твой случай, то есть мы прочитали столько байт, сколько хотели.
              break;

W0LF,  со мной то как раз стоит спорить smile. Всё знать не возможно, а из спора истина рано или поздно возрадиться. 
Но с этим avaliable() были у меня неприятные моменты, то есть действительно приходил нуль, моделей не помню, но на многих мобилках такое наблюдалось. Поэтому, кто предупреждён - тот вооружён! smile

Автор: vandaler 2.1.2010, 20:26
у меня ещё вопросец по поводу получения файла:
в одном потоке есть цикл, который постоянно запрашивает и получает файл (побайтово). как бы мне остановить этот процесс независимо от того, на какой стадии он находится? я пытался просто закрывать сокет, а в этом цикле ловить исключение и проверять от чего оно вылезло: если от моего закрытия, то все ок и алерт не вызывается. почему-то время от времени моя программа вылетает 

Автор: W0LF 3.1.2010, 19:07
Object.wait(), Object.notify(), Object.notifyAll();
снова повторюсь, есть пример с WTK, там в примере с сокетами как раз показывают как правильно остановить, приостановить и тп

Автор: vandaler 4.1.2010, 13:23
спасибо, буду разбираться!

Автор: vandaler 6.1.2010, 21:59
WOLF, извини, но у меня не вышло. подскажи, подалуйста. Вот функция, работу которой надо остановить:
Код

    public void giveMeScreen()
    {
        try{
             String msg = "ls\0";
             byte[] data = msg.getBytes();
             os.write(data);
             os.flush();
             Image temp = null;
             int size = 0;
             for (i=0; i<5; i++)
             {
                size = size*10 + is.read() - 48;
             }
             byte[] im = new byte[size];
             for (i=0; i<size; i++)
             {
                im[i] = (byte)is.read();
             }
             temp = Image.createImage(im, 0, size);
             screen = Image.createImage(temp, 0, 0, temp.getWidth(), temp.getHeight() ,Sprite.TRANS_ROT90);
       }
        catch (Exception e){error(e.toString()+" in getting of file getting");}

хотелось бы остановить поток, где работает эта ф-ия, но сокет не закрывать.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)