Newsgroup: it.comp.java
Titolo: [newbie]Performance e metodi write(),read()

/*
Ciao a tutti,
Ho creato un piccolo metodo che suddivide un file di input
in piu sottofile di dimensione parametrizzabile via console.
(1)
Il mio problema è l'estrema lentezza  con cui si svolge il
tutto; infatti dividendo 400kb in due sottofile di 200kb ci
mette circa 54 secondi.
Il che vuol dire che circa 9 Mbyte di input diventano 20
minuti di elaborazione.
Un'infinità.
Nella prima versione facevo un'operazione del tipo:
--------------------------------
output.write(input.read());
--------------------------------
tuttavia cercando di ottimizzare ho pensato di caricare
tutto il file input all'interno di un int[] Array,
scrivendolo poi un poco alla volta negli output.
Un miglioramento c'è stato passando dai ca. 6800 byte al
secondo di esecuzione totale ai ca. 7750 byte al secondo, ma
il tutto è ancora assolutamente troppo lento [vedi sopra].
Cosa potrei fare?
Avrei anche un'altra domanda:
************************************************************
****
(2)
Se i metodi di FileInputStream.read() e
FileInputStream.write() leggono e scrivono un int (16bit)
perchè il mio programma funziona "benissimo" con cicli che
poggiano sul numero di byte(8bit) ?
In che senso leggono e scrivono int?
Avro sicuramente scritto molte sciocchezze e il codice che
segue farà SICURAMENTE rabbrividire i piu esperti ma se
qualcuno ha la pazienza di aiutarmi lo ringrazio fin da ora.
ciao Samuele
segue se necessario il codice del metodo in questione:
*/
public static void Divider()
{
 long MaxByteOutput=0;
 long TotalByteInput=0;
 long TotalByteCopyiedFile=0;
 long LocalByteCopyied=0;
 int switch_errore=0;
 DataInputStream da_tastiera=new DataInputStream(System.in);
 FileInputStream Input=null;
 String NomeInput="";
 String NomeOutput="";
do
 {
 switch_errore=0;
 System.out.println("Inserire il <NOME_FILE>.<ESTENSIONE> da
dividere");
 System.out.println("[path obbligatorio se diverso da quello
di residenza del PGM]:");
 try{NomeInput=da_tastiera.readLine();}
 catch(IOException err){System.out.println("Errore
nell'input tastiera");switch_errore=1;}
 try{Input=new FileInputStream(NomeInput);}
 catch(IOException err){System.out.println("Errore nella
inizializzazione file input");switch_errore=1;}
 }
while(switch_errore!=0);
try{TotalByteInput=Input.available();System.out.println("Dim
ensione "+NomeInput+"\n [Kilobyte]="+TotalByteInput/1024);
         System.out.println(" [byte]    ="+TotalByteInput);
         System.out.println("
[Megabyte]="+TotalByteInput/1048576);}
catch(IOException err){System.out.println("Errore nella
rilevazione dimensioni FILE input");}
 System.out.println("Inserire la dimensione massima dei
sottofile[byte]:");
do
{
 switch_errore=0;
 try{MaxByteOutput=Long.parseLong(da_tastiera.readLine());
  if(TotalByteInput<=MaxByteOutput)
   {System.out.println("Il file output deve essere piu
piccolo dell'input");switch_errore=1;}
   ;}
 catch(IOException err){System.out.println("Errore
nell'input tastiera");switch_errore=1;}
 catch(NumberFormatException
err){System.out.println("Inserire valore
numerico!");switch_errore=1;}
 }
while(switch_errore!=0);
int[] ArrayInt=new int[(int)TotalByteInput];
long
NumeroTotaleFileOutput=(TotalByteInput/MaxByteOutput)+1;
  /*quello che segue è il caricamento dell'array di appoggio
per disaccoppiare il processo di
  lettura da quello di scrittura*/
  for(LocalByteCopyied=0;LocalByteCopyied<TotalByteInput;)
   {
    try{
     ArrayInt[(int)LocalByteCopyied]=Input.read();
     }
    catch(IOException err)
     {
     System.out.println("Errore in caricamento array");
     }
    LocalByteCopyied++;
   }
System.out.println("NumeroTotaleFileOutput
="+NumeroTotaleFileOutput);
FileOutputStream[] Output=new
FileOutputStream[(int)NumeroTotaleFileOutput];
for(int
NumberOfOutput=0;TotalByteCopyiedFile<TotalByteInput;NumberO
fOutput++)
 {
  NomeOutput= NumberOfOutput+NomeInput;
  try{
   Output[NumberOfOutput]=new FileOutputStream(NomeOutput);
   System.out.println("output:"+NumberOfOutput+" allocato");
   }
  catch(IOException err)
   {
    System.out.println("Errore in apertura output
numero:"+NumberOfOutput);
   }
  catch(NullPointerException err)
   {
    System.out.println("File "+NomeOutput+" con NULL POINTER
EXCEPTION");
   }
  /*quello che segue è lo scaricamento dell'array di
appoggio per disaccoppiare il processo di
  lettura da quello di scrittura*/
for(LocalByteCopyied=0;TotalByteCopyiedFile<TotalByteInput&&
LocalByteCopyied<MaxByteOutput;)
   {
    try{
Output[NumberOfOutput].write(ArrayInt[(int)LocalByteCopyied]
);
     }
    catch(IOException err)
     {
     System.out.println("Errore in scrittura output");
     }
    LocalByteCopyied++;
    TotalByteCopyiedFile++;
   }
 }
}

Ciao,
potresti provare ad usare i BufferedInputStream e BufferedOutputStream.
Infatti leggere e scrivere un singolo byte alla volta non e' sicuramente
performante. Nel tuo codice leggi e scrivi comunque un singolo byte alla
volta anche quando usi gli array: l'unica cosa che hai cambiato e' il
momento in cui li scrivi (anziche' alternare lettura e scrittura, prima
fai tutte le letture e poi tutte le scrittue. Un leggero miglioramento
c'e', ma marginale). Se vuoi comunque gestire tu i buffer dovresti usare i
metodi read e write che prevedono degli array come parametri
(read(byte[]), write(byte[]) e simili). Comunque, visto che esistono gia'
le classi Buffered... la cosa piu' semplice e' usarle.
La seconda domanda...
read e write usano gli int principalmente per un motivo: hanno bisogno
(almeno read) di un valore in piu' (-1), non compreso nel range di valori
di un byte, per indicare la fine dello stream. Il fatto che anche write
poi usi int e' per coerenza con read e per evitare di dover scrivere
codice con continui cast. Quindi usano gli int, trattandoli come byte
unsigned, con valori fra 0 e 255. (invece il tipo byte e'
signed, con valori fra -128 e 127).
-- 
Lucio Benfante
Brainbench MVP for Java 1
http://www.brainbench.com
MyTranscript: 
http://www.brainbench.com/transcript.jsp?pid=167064

Grazie per le informazioni mi sono state molto utili.
A beneficio di tutti posto un link che ho trovato cercando
informazioni sulla classe BufferedInput/OutputStream che mi
hai indicato.
http://www.mokabyte.it/1998/06/splitter.htm
Tra l'altro è esattamente il tipo di programmino che sto
cercando di realizzare.
Ciao Samuele