Java 将整个nio通道读入字符串

Java 将整个nio通道读入字符串,java,nio,Java,Nio,我需要将ReadableByteChannel(例如文件通道)读入字符串。我不能通过使用Channels.newReader或Channels.newInputStream包装通道来实现这一点,因为我不希望在收集包装时关闭通道。我也不想在中间字节缓冲区中存储所有字节 我想在循环中读取输入并调用CharsetDecoder.decodeByteBuffer、CharBuffer、boolean,但问题是当CharBuffer满时,它不会重新分配CharBuffer。解决方案看起来太复杂了: pub

我需要将ReadableByteChannel(例如文件通道)读入字符串。我不能通过使用Channels.newReader或Channels.newInputStream包装通道来实现这一点,因为我不希望在收集包装时关闭通道。我也不想在中间字节缓冲区中存储所有字节

我想在循环中读取输入并调用CharsetDecoder.decodeByteBuffer、CharBuffer、boolean,但问题是当CharBuffer满时,它不会重新分配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;
}

我不知道有任何声明或证据表明包装读取器或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,并在读取后对其进行修剪。这不是我说的,也没有解释为什么在垃圾收集流时通道不会关闭。