Visualizzazione dei risultati da 1 a 3 su 3
  1. #1

    Problema con l'InputStream!

    Ho un problema che mi rode dentro !

    Di seguito la parte centrale del problema:
    codice:
    int _headerread=0;
    int _byteread=0;
    int _dimMax = 1024;
    byte[] _buffer = new byte[_dimMax];
    byte[] _header = new byte[3];
    
    InputStream _br	= _client.retrieveFileStream(_fileName);
    
    while(_br.available()>0){
             //I read the header to get the lenght of next read. Transfer is in MODE BLOCK, so
             // after the first byte (0x80 or 0x40) I find 2 byte rappresenting the length.
             _headerread = _br.read(_header, 0, 3);
    
            if ((_header[0]  != (byte) 0x80) & (_header[0]  != (byte)0x40)){
    	        throw new Exception("Error while reading lotto: missing 0x80 and 0x40 in first byte"); 
            }
    
            //I compute the lenght.
            _l  	=  (_header[1] & 0x00ff)<<8 | (_header[2] & 0x00ff);
    
            //The lenght shouldn't never be bigger than _dimMax, but if it happens, I proceed with padding _buffer.
            if(_l > _buffer.length){
            _buffer = new byte[_l];
            }
            _byteread = _br.read(_buffer, 0, _l);
    
            //[...] COMPUTE OTHER 
    }

    Quello che faccio è una semplice operazione:
    1) Leggo un file da un server ftp;
    2) Essendo in block mode, ho leggo i primi 3 byte di intestazione e mi calcolo la lunghezza
    della prossima riga da leggere;
    3) Leggo la riga;
    4) Faccio altre operazioni
    5) Ripeto tutto fino a quando il file è finito.


    Il problema è che quando faccio la lettura della riga...non sempre ottengo i risultati sperati!
    Ad esempio ottengo che la prossima riga è 998 byte... (cioè _l = 998), ma dopo la lettura:

    codice:
     _byteread = _br.read(_buffer, 0, _l);
    ottengo che il numero di byte letti effettivamente è diverso: ad esempio _byteread = 550!!

    Sto impazzendo!!

    La cosa bella è che una soluzione c'è...e funziona tutto...
    Basta che aggiungo una pausa dopo (ma funziona anche prima!) la lettura:

    codice:
    int _headerread=0;
    int _byteread=0;
    int _dimMax = 1024;
    byte[] _buffer = new byte[_dimMax];
    byte[] _header = new byte[3];
    
    InputStream _br	= _client.retrieveFileStream(_fileName);
    
    while(_br.available()>0){
             //I read the header to get the lenght of next read. Transfer is in MODE BLOCK, so
             // after the first byte (0x80 or 0x40) I find 2 byte rappresenting the length.
             _headerread = _br.read(_header, 0, 3);
    
            if ((_header[0]  != (byte) 0x80) & (_header[0]  != (byte)0x40)){
    	        throw new Exception("Error while reading lotto: missing 0x80 and 0x40 in first byte"); 
            }
    
            //I compute the lenght.
            _l  	=  (_header[1] & 0x00ff)<<8 | (_header[2] & 0x00ff);
    
            //The lenght shouldn't never be bigger than _dimMax, but if it happens, I proceed with padding _buffer.
            if(_l > _buffer.length){
            _buffer = new byte[_l];
            }
            _byteread = _br.read(_buffer, 0, _l);
    
    
            Thread.sleep(_threadPause);	//_threadPause is 1, 2 or 3 milliseconds.
            //[...] COMPUTE OTHER 
    }

    Così funziona perfettamente! Ma mi sembra una cosa assurda!
    Possibile che abbia bisogno di una pausa per completare la lettura di soli 1000 byte???

    Il problema di questa soluzione è che il tempo di attesa cresce vertiginosamente con il numero di linee...

    Ci sono file con 300.000 righe...e 1 millisecondo x 300.000 righe fa 300 secondi...cioè 5 minuti di tempo morto...!
    Noto che in computer con maggiore potenza di calcolo 1 millisecondo basta, mentre in pc meno potenti devo aumentare la pausa!

    Che cosa posso fare????

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: Problema con l'InputStream!

    Originariamente inviato da koaowner84
    Il problema è che quando faccio la lettura della riga...non sempre ottengo i risultati sperati!
    Ad esempio ottengo che la prossima riga è 998 byte... (cioè _l = 998), ma dopo la lettura:

    codice:
     _byteread = _br.read(_buffer, 0, _l);
    ottengo che il numero di byte letti effettivamente è diverso: ad esempio _byteread = 550!!
    Specialmente quando il InputStream è relativo al networking (socket, ecc...) non è affatto detto che la read riempia tutto il buffer! Non c'è scritto da alcuna parte che deve riempire il buffer per quella lunghezza specificata.

    È compito tuo usare il valore di ritorno della read, capire se ha letto tutto ed eventualmente rieseguire N altre volte la read per leggere il resto (e o accodare o sostituire ... dipende).

    Oppure incapsuli il InputStream in un DataInputStream che ha il readFully, questo sì è garantito che riempie tutto il buffer a meno di: a) end-of-file (lancia EOFException) o b) errori di I/O (lancia IOException o più specifici).


    P.S: available() raramente serve, e non dice quanti byte ci sono in tutto! (leggere il javadoc).
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Grazie per la risposta...

    Premetto che
    codice:
    _br.available()
    l'ho messo li perchè ho dovuto fare un sunto del mio codice...e quindi per far capire più o meno il ciclo che fa...In realtà il while fa un altro controllo! Ma comunque ottima osservazione!

    Ho provato ad usare il readFully del DataInputStream...e purtroppo va sempre in eccezzione perchè non riesce mai a completare il recupero del file.


    Ma quindi ha senso il fatto che aggiungendo la pausa invece funzioni tutto??

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.