Java 将整个nio通道读入字符串
我需要将ReadableByteChannel(例如文件通道)读入字符串。我不能通过使用Channels.newReader或Channels.newInputStream包装通道来实现这一点,因为我不希望在收集包装时关闭通道。我也不想在中间字节缓冲区中存储所有字节 我想在循环中读取输入并调用CharsetDecoder.decodeByteBuffer、CharBuffer、boolean,但问题是当CharBuffer满时,它不会重新分配CharBuffer。解决方案看起来太复杂了:Java 将整个nio通道读入字符串,java,nio,Java,Nio,我需要将ReadableByteChannel(例如文件通道)读入字符串。我不能通过使用Channels.newReader或Channels.newInputStream包装通道来实现这一点,因为我不希望在收集包装时关闭通道。我也不想在中间字节缓冲区中存储所有字节 我想在循环中读取输入并调用CharsetDecoder.decodeByteBuffer、CharBuffer、boolean,但问题是当CharBuffer满时,它不会重新分配CharBuffer。解决方案看起来太复杂了: pub
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;
}
我不知道有任何声明或证据表明包装读取器或InputStream将在垃圾收集时关闭自身及其包装的通道 但如果你真的想要另一种方式,你可以使用扫描仪:
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;
}
我无法通过使用Channels.newReader或Channels.newInputStream包装通道来完成此操作
是的,你可以
因为我不想在收集包装器时关闭通道
不会的。直到对底层FileDescriptor的最后一个引用被垃圾收集,或者您自己关闭它,通道才会关闭
你似乎也不知道
您的问题完全没有动机。无法了解您要做的事情。但有两个想法可能会有所帮助。1.将parcial解码的内容存储在StringBuilder中,并在读取后将其包装到CharBuffer中。2.根据文件大小分配一个更大的CharBuffer,并在读取后对其进行修剪。这不是我说的,也没有解释为什么在垃圾收集流时通道不会关闭。