2012-09-24 9 views
6

In un servlet, sto creando una quantità molto grande di contenuto HTML in uno StringBuilder che, alla fine, deve essere scritto nel PrintWriter della risposta. Per utilizzare un PrintWriter, è necessario prima chiamare il metodo toString() di StringBuilder per ottenere il contenuto come String. Ma questo duplica inutilmente il contenuto. C'è un modo per scrivere direttamente da StringBuilder dato che è già in possesso del contenuto?Scrivere uno StringBuilder su un writer, senza toString()

PrintWriter può accettare un CharSequence, ma la documentazione afferma che chiama toString() di CharSequence, quindi non è di grande aiuto.

L'unico modo chiaro che posso vedere è usare il metodo charAt (i) di StringBuilder per ottenere e scrivere un carattere alla volta, ma questo sarebbe un miglioramento?

+2

Il miglioramento è relativo. Se il tuo obiettivo è ridurre il consumo di memoria, allora sì, sarebbe un miglioramento. Dovresti testare se è più lento. Non sarei sorpreso se, a causa del buffering del flusso di output, la penalizzazione delle prestazioni non fosse poi così grande. –

risposta

7

In alternativa, è possibile eliminare StringBuilder e utilizzare uno StringWriter e uno PrintWriter.

+0

Devo prendere il contenuto HTML e scriverlo sul PrintWriter della Servlet, che si ottiene chiamando il metodo getWriter() di HttpServletResponse. Non vedo un modo per combinare questo con un StringWriter. – worpet

2

Si può solo scrivere al PrintWriter, in primo luogo, piuttosto che alla StringBuilder ...

Utilizzando charAt sarebbe non sicuramente aiutare. Produrrebbe prestazioni molto scarse per farlo in questo modo. Se si in realtà si desidera procedere in tale direzione è possibile utilizzare il metodo StringBuilder.subString(start,end). Questo metodo consente di leggere ad esempio 1000 caratteri alla volta e di stamparlo su PrintWriter ...

+0

'StringBuilder.substring()' assegnerà una nuova stringa ogni volta che la chiami. Anche se la quantità totale di memoria allocata sarà più piccola, il davanzale imporrà un sacco di spese generali. In realtà penserei che usare charAt() non sia poi così male perché molto probabilmente il PrintWriter di Servlet è comunque bufferizzato. –

2

La classe StringBuilder memorizza la stringa in un array di caratteri interno. Il problema è che questo array di caratteri non è accessibile.

soluzioni proposte:

1) si potrebbe creare una nuova classe che estende ObjectOutputStream, dove l'override del metodo writeObjectOverride(Object obj). Quindi serializza semplicemente l'istanza StringBuilder in cui hai costruito il tuo documento HTML. Il metodo sostituito writeObjectOverride(Object obj) verrà chiamato con il char array interno di Stringbuilder che fa parte del processo di serializzazione e voilà: si ha il riferimento al char array interno del builder String, è tuo per scriverlo sul PrintWriter di Servlet output ... Nota: il tuo metodo writeObjectOverride() verrà chiamato più volte, ovviamente puoi ignorare quelli che ti passano qualcosa di diverso dal char array desiderato.

2) È possibile utilizzare la classe CharBuffer anziché StringBuilder che ha il metodo array() che restituisce l'array interno. CharBuffer non ha tante operazioni di aggiunta (o inserimento) come StringBuilder, quindi sarebbe necessario estenderle un po '(a seconda di cosa è esattamente necessario) ...

3) È possibile scrivere la propria implementazione di StringBuilder, o meglio cosa si usa da esso. In questo modo avresti accesso all'oggetto (un array di caratteri, ad esempio) in cui memorizzi il testo assemblato ...

+0

Non sono sicuro che la soluzione 1 funzionerebbe perché per scrivere writeObjectOverride è necessario riscrivere la maggior parte della logica di serializzazione perché il costruttore di un parametro ObjectOutputStream disabilita la chiamata a writeObjectOverride. non è progettato per essere usato in questo modo. Inoltre non ci sono altri metodi che potreste chiamare all'interno di writeObjectOverride per gestire il caso normale. Potresti usare la riflessione, ma il responsabile della sicurezza potrebbe mettersi sulla tua strada. – cquezel