Newsgroup: it.comp.java
Titolo: Copia stdio su stdout

Mando due programmi che copiano l'input sull'output. Sono entrambi
sofferenti di malfunzionamenti simili e vorrei un vostro parere.
//legge stdin una riga alla volta e lo riscrive su stdout
import java.io.*;
class Identico
{
public static void main(String argv[]) throws Exception
{
  BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
  while(true)
  {
   String line=r.readLine();
   if (line==null) break;
   else     System.out.println(line);
  }
}
}
//legge stdin un carattere alla volta e lo riscrive su stdout
import java.io.*;
class Identico
{
public static void main(String argv[]) throws Exception
{
  BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
  while(true)
  {
   int c=r.read();
   if (c!=-1)  System.out.print((char)c);
   else    break;
  }
}
}
Il primo copia il file carattere per carattere, il secondo riga per riga. Si
comportano scorrettamente quando l'ultimo carattere dell'input e' diverso
dall'acapo, ovvero quando non si precede il Ctrl-Z dal tasto di invio
(Esempio che non funziona: abc[CTRL-Z]; Esempio che funziona:
abc[Invio][Ctrl-Z]). In tal caso i programmi non copiano l'input (il 90%
delle volte) e non terminano.
Inoltre pur funzionando con la redirezione dell'input (es che funziona: java
Identico < file.txt) non funzionano con la pipe (es: java Identico | dir).
Avete qualche idea del perche' di questi malfunzionamenti e/o consigli?
Ultimissima cosa. I programmi in questione funzionavano correttamente sotto
W95 e JDK1.2. Non funzionano sotto l'ultima versione del JDK (1.3) con W98.
W.

 ...
Il metodo readLine() è noto per creare un sacco di problemi relativi proprio
al modo in cui sono terminate le linee dello stream in input (cfr. Java I/O
di E. R. Harold.) Per quanto ho potuto riscontrare (win98, jdk1.3) entrambi
i programmi funzionano bene con la redirezione dell'input (input proveniente
da file), comunque sia terminato il file (CR, LF, CR+LF od un carattere
qualsiasi.)
I problemi sorgono quando l'input deriva da tastiera o in generale da uno
stream la cui lunghezza non è definita a priori (ad esempio uno stream da un
server http.) Infatti readLine() talvolta si pianta perché rimane in attesa
di conoscere quale sia il prossimo carattere in modo da poter decidere se la
linea sia terminata o meno. Nel caso dell'input da tastiera, funziona
correttamente la sequenza CTRL-M - CTRL-Z oppure la sequenza CTRL-Z -
CTRL-Z. Un solo CTRL-Z a fine linea non basta a readLine() per poter
decidere se l'input è terminato. Tuttavia non escludo che questo
comportamento sia frutto, in qualche modo, anche di circostanze sistema
operativo-dipendenti.
Riguardo alla pipe, non funziona perché la sintassi che hai usato non è
corretta. Un comando del tipo:
java identico | dir
significa: redirigi l'output di "java identico"  attraverso l'input di
"dir". Ma dir non gestisce alcun input! (semplicemente visualizza la
directory)
Forse intendevi qualcosa del genere:
dir | java identico
Oppure puoi provare:
java identico | sort
che ordina l'output del programma. O ancora:
java identico < input.txt | sort > output.txt
che prende l'input dal file input.txt e lo scrive, ordinato, nel file
output.txt.
"Take home message": readLine() non è un metodo affidabile per gestire
stream di lunghezza non nota, meglio farne a meno.
Marco.
--
Per scrivermi direttamente elimina
__TOGLIMI__ dall'indirizzo e-mail.

stream di lunghezza non nota, meglio farne a meno.
Intendi proprio stream di lunghezza non nota o stream di lunghezza non
prefissata?
Grazie per la risposta, mi hai tolto un peso. Ora riprendo a fare
prove.