我需要在字符串中读取ReadableByteChannel
(例如FileChannel
)。我不能通过使用Channels.newReader()
或Channels.newInputStream()
封装频道来实现此目的,因为我不希望在收集包装时关闭频道。我也不想将所有字节存储在中间ByteBuffer
。
我想在循环中读取输入并调用CharsetDecoder.decode(ByteBuffer, CharBuffer, boolean)
,但问题是它在填满时不会重新分配CharBuffer。解决方案看起来太复杂了:
public static CharBuffer readAll(final ReadableByteChannel ch, final Charset cs)
throws IOException {
final ByteBuffer bb = ByteBuffer.allocate(3);
CharBuffer cb = null;
final CharsetDecoder dec = cs.newDecoder();
while (ch.read(bb) > 0) {
bb.flip();
cb = mydecode(dec, cb, bb);
bb.clear();
}
bb.flip();
dec.decode(bb, cb, true);
cb.flip();
return cb;
}
// modified CharsetDecoder.decode(ByteBuffer)
private static CharBuffer mydecode(final CharsetDecoder dec, CharBuffer out, final ByteBuffer in)
throws CharacterCodingException {
int n = (int) (in.remaining() * dec.averageCharsPerByte());
if (out == null) {
out = CharBuffer.allocate(n);
}
if ((n == 0) && (in.remaining() == 0)) {
return out;
}
// dec.reset();
for (;;) {
final CoderResult cr = in.hasRemaining() ? dec.decode(in, out
// , true
, false) : CoderResult.UNDERFLOW;
if (cr.isUnderflow()) {
// cr = dec.flush(out);
}
if (cr.isUnderflow()) {
break;
}
if (cr.isOverflow()) {
n = 2 * n + 1; // Ensure progress; n might be 0!
final CharBuffer o = CharBuffer.allocate(n);
out.flip();
o.put(out);
out = o;
continue;
}
cr.throwException();
}
// out.flip();
return out;
}
答案 0 :(得分:0)
我不知道任何声明或证据表明包装Reader或InputStream会在收集垃圾时自行关闭(以及它包装的Channel)。
但如果您真的想要其他方式,可以使用扫描仪:
public static String readAll(final ReadableByteChannel ch,
final Charset cs)
throws IOException {
Scanner s = new Scanner(ch, cs.name());
String text = s.useDelimiter("\\z").next();
IOException e = s.ioException();
if (e != null) {
throw e;
}
return text;
}
答案 1 :(得分:0)
我无法通过使用
打包频道来实现此目的Channels.newReader()
或Channels.newInputStream()
是的,你可以。
因为我不希望在收集包装器时关闭通道
不会。在对基础FileDescriptor
的最后一次引用进行垃圾收集之前,或者您自己特意关闭它之前,通道不会关闭。
您似乎也不了解CharBuffer CharsetDecoder.decode(ByteBuffer in)
。
你的问题完全没有动力。