UPDATE2:我自己的适配器版本,只在构造函数中调用instanceof
并在flush()
和close()
函数中使用(Java 1.5)delta(避免需要)对于任何反射或对象构造后的逻辑),包含在本文的底部。 UPDATE1:Marc Baumbach编写了一个简单的适配器,这正是我需要的。包括在下面。原始问题如下。
需要java.lang.Appendable
的功能可以接受java.io.Writer
,因为Writer
实现Appendable
。
另一种方式呢?我正在使用一个需要编写器的函数,我正在尝试创建另一个调用它的函数,它接受一个可附加的函数并将其传递给原始的writer函数。
我看到您可以扩展Writer
,这是抽象的,并将所有write(...)
函数重定向到相应的append(...)
- s。但是你还必须实现flush()
和close()
,我很清楚如何干净地编写它们,以便这个包装类可以接受任何 Appendable。
我很惊讶没有任何东西可以在网络或stackoverflow上,或者在现有的库中解决这个问题。至少不是我能找到的。
我很感激这里的一点指导。谢谢。
回答此问题的适配器代码。由Marc Baumbach撰写(我自己的版本如下):
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();
}
}
}
这是我自己的版本,基于Marc,仅在构造函数中使用instanceof
,在flush()
和close()
中仅使用(Java 1.5)delta。这是为了避免在对象构造之后使用任何逻辑或反射。这也是gist:https://gist.github.com/aliteralmind/8494917
该类包含一个演示,后跟两个无用的增量(一个Flushable
,一个Closeable
),主函数(newWriterForAppendable(apbl)
),然后是适配器类本身。
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> <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();
}
}
答案 0 :(得分:1)
通常在Writer
中,flush()
和close()
用于清除可能尚未提交或发送到流的任何其他写入。只需将所有write
方法直接重定向到append
中的Appendable
方法,您就不必担心flush()
和close()
,除非您{ {1}}实施Appendable
和/或Closeable
。
一个很好的例子就像BufferedWriter。当您在其上调用Flushable
时,它可能不会立即将所有字节发送到最终输出/流。在您write()
或flush()
之前,有些字节可能无法发送。为了绝对安全,我会测试包裹的close()
,如果它是Appendable
或Closeable
在相应的方法中并投射它并执行操作。
这是一个非常标准的设计模式,名为Adapter pattern。
以下是此适配器的良好实现:http://pastebin.com/GcsxqQxj
答案 1 :(得分:0)
您可以接受任何Appendable
,然后检查它是Writer
到instanceof
。然后执行向下转换并调用仅接受Writer
的函数。
示例:
public void myMethod(Appendable app) throws InvalidAppendableException {
if (app instanceof Writer) {
someObj.thatMethod((Writer) app);
} else {
throw new InvalidAppendableException();
}
}
答案 2 :(得分:0)
Google的Guava有一个简单的实用工具:CharStreams.asWriter
实施不是最快的(see),如果你想获得最佳性能,你可能想看一下spf4j Streams.asWriter