Newsgroup: it.comp.java
Titolo: Come faccio a creare un InputStream?

Vorrei scrivere una classe che genera un InputStream XML leggendo i dati
(una riga per volta) da una stored procedure Oracle. Mi serve un
InputStream perchè così lo posso passare alla Transformer.transform
(JAXP) per effettuare la trasformazione XSL.
Ecco il punto: come faccio a creare un InputStream??? Anche lasciando
perdere la stored procedure, supponiamo di volere creare un InputStream
partendo da una sequenza di stringhe che mi vengono ritornate da un
sistema sottostante (Oracle, nel mio caso). Come faccio? Vorrei evitare
di infilare tutte le stringhe in uno StringBuffer per evitare problemi
di memoria, e passare per un file temporaneo mi sembra poco pulito.
Ho provato a studiarmi le Java pipes (JavaInputStream e
JavaOutputStream) ma confesso di non essere riuscito a farle funzionare.
Qualche idea?
-- 
Cristian Veronesi ><((((º> 
http://www.crpa.it
"I'm doing a (free) operating system (just a hobby, won't be big and
professional like gnu)..." [Linus Torvalds, comp.os.minix, 25-08-1991]

 JavaOutputStream) ma confesso di non essere riuscito a farle funzionare.
Pardon: volevo dire PipedInputStream e PipedOutputStream.


JavaOutputStream) ma confesso di non essere riuscito a farle funzionare.
Non e' complicato in line di principio, ma ci sono due punti da tener
presenti. 
Uno, il sistema sottostante deve fornirti un metodo/oggetto per
bufferizzare il tuo risultato al di fuori della memoria della JVM - ad
esempio un java.sql.ResultSet nel caso di un database. Due, quest'oggetto
deve essere isolato dal sistema che l'ha generato, che e' la cosa
complicata coi db relazionali - complicata perche' rischi di creare o
bottlenecks o race conditions. In pratica, il tuo risultato deve restare
costante se il contenuto delle tavole sotto cambia concorrentemente. Come
questo si faccia dipende parecchio dal driver JDBC, dal server e dal
sistema di transazioni distribuite, se c'e'. Se hai un sistema
transazionale, in genere puoi aprire una transazione in una modalita' che
non permette dirty reads.. pero' questo puo' significare che in caso di
modifiche concorrenti il tuo resultset fallisce, che non e' bello 
(ammenoche' non sia okay per la semantica che vuoi dare al tuo stream). 
In genere il server *deve* fare una copia temporanea del risultato, se
necessario.. e nei casi peggiori questo comportamento lo puoi simulare
copiando il risultato in una tavola temporanea, e rifacendo una select da
li'. Ovviamente questo e' inefficiente. 
I piped stream sono una buona soluzione solo se sei ragionevolmente
sicuro che lettura e scrittura avvengano concorrentemente - dato che il
pipe buffer e' limitato ad 1K.
Implementare un InputStream poi, e' semplice: in primo luogo devi
definire la "presentazione" dello stream al codice client, poi devi
semplicemente implementare il metodo read(char ch[], int off, int len)
(che riempie di caratteri l'array ch dalla posizione off per len
caratteri al piu') in modo che traduca l'oggetto "interno" in tale
presentazione. 
(Gli stream standard chiamano sempre read(...) con len = 1, ma per 
sicurezza deve funzionare con len arbitraria).
In genere questo implica mantenere un piccolo buffer locale e un flag di
stato che guida il comportamento di read (tipo READ_FROM_SET,
READ_FROM_MEMORY) eccetera: in pratica una semplice macchina a stati. Nel
caso del resultSet, leggi una riga, ne fai l'encoding in un buffer locale
allo stream, e il tuo stream legge da tale buffer finche' non e'
esaurito, etc. 
Devo mettere sul web da qualche tempo una classe di utilita' che, ad
esempio, lavora come un piccolo analizzatore lessicale/preprocessore,
riconoscendo macro in uno stream e presentando quindi lo stream
"risolto", con le macro sostiuite dai valori. 
Se ti puo' servire come esempio lo posso postare.
-- 
Life's something u don't get out alive..
ObjectZone - 
http://space.tin.it/computer/csadun

 Qualche idea?
"java.io.SequenceInputStream" ti puň aiutare?
Ciao

 "java.io.SequenceInputStream" ti può aiutare?
Ti ringrazio - e colgo l'occasione per ringraziare anche Cristiano Sadun
per la sua lunga ed esauriente risposta - ma alla fine ho risolto con le
pipes. Sull'onda dell'entusiasmo, posto qui un esempietto "gnocco" come
dicono dalle mie parti ad uso e consumo dei tontoloni come me (se ce ne
sono altri).
La classe StringProducer produce una sequenza di stringhe e le stampa su
di un PrintWriter. La classe Readr ha un metodo getInputStream che legge
la sequenza di stringhe prodotta da StringProducer e le trasforma in un
InputStream.
---------- StringProducer.java ----------
import java.io.* ;
public class StringProducer extends Thread {
  private PrintWriter writer ;
  public StringProducer (PrintWriter pw) {
    writer = pw ;
  }
  public void run () {
    String nomi[] = {"Ciccio","Pippo","Mario","Pino","Rino","Gino"} ;
    int i ;
    for (i=0; i<nomi.length; i++) {
      writer.println(nomi[i]) ;
      writer.flush() ;
      try {
        Thread.sleep(1000);
      } catch (Exception ex) {}
    }
   writer.close();
  }
}
---------- Readr.java ----------
import java.io.* ;
public class Readr {
  public InputStream getInputStream () throws IOException {
    PipedOutputStream pos = null ;
    PipedInputStream pis = null ;
    pos = new PipedOutputStream () ;
    pis = new PipedInputStream (pos) ;
    PrintWriter pw = new PrintWriter (pos) ;
    Thread t = new StringProducer (pw) ;
    t.start() ;
    return pis ;
  }
  public static void main (String args[]) throws Exception {
    Readr rdr = new Readr() ;
    InputStream is = rdr.getInputStream () ;
    BufferedReader br = new BufferedReader(new InputStreamReader(is)) ;
    String line ;
    while ((line=br.readLine())!=null) {
      System.out.println(line) ;
    }
 
  }
}
Ovviamente eventuali osservazioni sono più che benvenute...
Ciao, Cris


 wrote in message
news:3BA8514F...@crpa.it...
