write java io writer

Cómo envolver un java.lang.Appendable en un java.io.Writer?



outputstream write java (3)

Normalmente en un Writer , el flush() y close() están ahí para limpiar cualquier escritura adicional que no se haya confirmado o enviado a la transmisión. Simplemente redireccionando todos los métodos de write directamente a los métodos de append en el Appendable no tendrás que preocuparte por flush() y close() menos que tus implementos se Appendable y / o Flushable .

Un buen ejemplo es algo así como BufferedWriter . Cuando llame a write() sobre eso, es posible que no envíe todos los bytes a la salida / secuencia final inmediatamente. Es posible que algunos bytes no se envíen hasta que lo flush() o lo close() . Para estar absolutamente seguro, probaría el Appendable envuelto si es Flushable o Flushable en el método correspondiente y lo Flushable y realizaré la acción también.

Este es un patrón de diseño bastante estándar llamado patrón de Adaptador .

Aquí está lo que probablemente sea una buena implementación para este adaptador: http://pastebin.com/GcsxqQxj

UPDATE2: Mi propia versión de la clase de adaptador, que solo llama a instanceof en el constructor y utiliza un delta (Java 1.5) en las funciones flush() y close() (evitando la necesidad de reflexión o lógica después de la construcción del objeto), incluido en la parte inferior de esta publicación. ACTUALIZACIÓN1: Marc Baumbach escribió un Adaptador simple que es exactamente lo que necesito. Incluido a continuación. La pregunta original sigue.

Una función que requiere un java.lang.Appendable puede aceptar un java.io.Writer , porque Writer implementa Appendable .

¿Qué acerca del otro camino alrededor? Estoy usando una función que requiere un escritor, y estoy tratando de crear otra función que lo llame, que acepta un apéndice y lo pasa a la función de escritura original.

Veo que puede extender Writer , que es abstracto, y redirigir todas las funciones de write(...) a sus correspondientes append(...) -s. Pero también debe implementar flush() y close() , y no tengo ningún problema en cómo escribirlos limpiamente para que este wrapper-class pueda aceptar cualquier Appendable.

Me sorprende que no haya nada por ahí, ya sea en la web o stackoverflow, o en una biblioteca existente, que solucione esto. Al menos no que yo pueda encontrar.

Agradecería una pequeña guía aquí. Gracias.

Código de adaptador que responde a esta pregunta. Escrito por Marc Baumbach (mi propia versión está abajo):

import java.io.Closeable; import java.io.Flushable; import java.io.IOException; import java.io.Writer; public class AppendableWriterAdapter extends Writer { private Appendable appendable; public AppendableWriterAdapter(Appendable appendable) { this.appendable = appendable; } @Override public void write(char[] cbuf, int off, int len) throws IOException { appendable.append(String.valueOf(cbuf), off, len); } @Override public void flush() throws IOException { if (appendable instanceof Flushable) { ((Flushable) appendable).flush(); } } @Override public void close() throws IOException { flush(); if (appendable instanceof Closeable) { ((Closeable) appendable).close(); } } }

Aquí está mi propia versión, basada en la de Marc, que solo usa instanceof solo en el constructor, y un delta (Java 1.5) en flush() y close() . Esto es para evitar tener que usar cualquier lógica o reflejo después de la construcción del objeto. Esto también se publicó como una idea central : https://gist.github.com/aliteralmind/8494917

Esta clase contiene una demostración, seguida de dos deltas sin Flushable (uno que se puede Flushable , uno que se puede Closeable ), la función principal ( newWriterForAppendable(apbl) ) y luego la clase del adaptador.

import java.io.Closeable; import java.io.Flushable; import java.io.IOException; import java.io.Writer; /** <P>{@code java NewWriterForAppendable}.</P> **/ public class NewWriterForAppendable { /** <P>Demonstrates {@code newWriterForAppendable(apbl)} for creating a new {@code Writer} that wraps around {@code System.out} (writes to the console).</P> **/ public static final void main(String[] igno_red) { try { NewWriterForAppendable.newWriterForAppendable(System.out).write("hello"); } catch(IOException iox) { throw new RuntimeException("WriterForAppendableXmpl", iox); } } /** <P>A {@code Flushable} whose {@code flush()} function does nothing. This is used by {@link #newWriterForAppendable(Appendable ap_bl) newWriterForAppendable}{@code (apbl)} as a (Java 1.5) delta.</P> @see #newWriterForAppendable(Appendable) newWriterForAppendable(apbl) **/ public static final Flushable FLUSHABLE_DO_NOTHING = new Flushable() { public void flush() { } }; /** <P>A {@code Closeable} whose {@code close()} function does nothing. This is used by {@link #newWriterForAppendable(Appendable ap_bl) newWriterForAppendable}{@code (apbl)} as a (Java 1.5) delta.</P> @see #newWriterForAppendable(Appendable) newWriterForAppendable(apbl) **/ public static final Closeable CLOSEABLE_DO_NOTHING = new Closeable() { public void close() { } }; /** <P>Creates a new {@code java.io.Writer} that wraps around a {@code java.lang.Appendable}. It properly {@link java.io.Writer#flush() flush}es and {@link java.io.Writer#close() close}s appendables that happened to also be {@link java.io.Flushable}s and/or {@link java.io.Closeable Closeable}s. This uses {@code instanceof} only in the constructor, and a delta in {@code flush()} and {@code close()}, which avoids having to use any logic or reflection after object construction.</P> <P>This function is released as a <A HREF="https://gist.github.com/aliteralmind/8494917">gist</A>, and is an example of the <A HREF="http://en.wikipedia.org/wiki/Adapter_pattern#Object_Adapter_pattern">Object Adapter pattern</A>. Thanks to <A HREF="http://stackoverflow.com/users/1211906/marc-baumbach">Marc Baumbach</A> on <A HREF="http://stackoverflow.com">{@code stackoverflow}</A> for the assistance. See (viewed 1/18/2014) <BR> &nbsp; &nbsp; <CODE><A HREF="http://stackoverflow.com/questions/21200421/how-to-wrap-a-java-lang-appendable-into-a-java-io-writer">http://stackoverflow.com/questions/21200421/how-to-wrap-a-java-lang-appendable-into-a-java-io-writer</A></CODE></P> @return A new writer that uses an appendable to do its output. @see #FLUSHABLE_DO_NOTHING @see #CLOSEABLE_DO_NOTHING **/ public static final Writer newWriterForAppendable(Appendable ap_bl) { return (new WFA(ap_bl)); } private NewWriterForAppendable() { throw new IllegalStateException("constructor: Do not instantiate."); } } class WFA extends Writer { private final Appendable apbl; private final Flushable flbl; private final Closeable clbl; public WFA(Appendable ap_bl) { if(ap_bl == null) { throw new NullPointerException("ap_bl"); } apbl = ap_bl; //Avoids instanceof at every call to flush() and close() flbl = (Flushable)((ap_bl instanceof Flushable) ? ap_bl : NewWriterForAppendable.FLUSHABLE_DO_NOTHING); clbl = (Closeable)((ap_bl instanceof Closeable) ? ap_bl : NewWriterForAppendable.CLOSEABLE_DO_NOTHING); } @Override public void write(char[] a_c, int i_ndexStart, int i_ndexEndX) throws IOException { apbl.append(String.valueOf(a_c), i_ndexStart, i_ndexEndX); } @Override public Writer append(char c_c) throws IOException { apbl.append(c_c); return this; } @Override public Writer append(CharSequence c_q) throws IOException { apbl.append(c_q); return this; } @Override public Writer append(CharSequence c_q, int i_ndexStart, int i_ndexEndX) throws IOException { apbl.append(c_q, i_ndexStart, i_ndexEndX); return this; } @Override public void flush() throws IOException { flbl.flush(); } @Override public void close() throws IOException { flush(); clbl.close(); } }


Puede aceptar cualquier Appendable y luego verificar si es un Writer mediante instanceof . Luego realice un downcast y llame a esa función que solo acepta Writer .

ejemplo:

public void myMethod(Appendable app) throws InvalidAppendableException { if (app instanceof Writer) { someObj.thatMethod((Writer) app); } else { throw new InvalidAppendableException(); } }


Google''s Guava tiene una utilidad simple para hacer esto: CharStreams.asWriter

La implementación no es la más rápida ( ver ), si quieres el mejor rendimiento, es posible que desees consultar spf4j Streams.asWriter