2017-07-10 9 views
-2

ReadableByteChannel(たとえば、FileChannel)を文字列にする必要があります。私はラップトップが収集されたときにチャネルを閉じたくないので、Channels.newReader()またはChannels.newInputStream()でチャネルをラップすることでこれを行うことはできません。私はまたすべてのバイトを中間に保存したくありませんByteBuffernioチャンネル全体を文字列に読み取る

ループ内の入力を読み込み、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

あなたがしようとしているものを得ることができませんでした。しかし、2つのイデアリアが役立つことがあります。 1.パラレルデコードされたコンテンツをStringBuilderに格納し、読み込み後にCharBufferにラップします。 2.ファイルサイズに基づいてより大きなCharBufferを割り当て、読み込み後にトリミングします。 – fhofmann

答えて

0

私が収集したゴミされると任意のステートメントまたはラッピングReaderまたはの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; 
} 
+0

これは私が言ったことではなく、ストリームがガベージコレクションされたときにチャネルが閉じられない理由を説明しません。 – EJP

+0

@EJPあなたが正しいです、私は誤解しました。更新しました。 – VGR

0

を私はChannels.newReader()またはChannels.newInputStream()

はいあなたができるとチャンネルをラップすることによってこれを行うことはできません。

ラッパーが

を収集したとき、私は、チャネルを閉じることにしたくないので、それはできません。元のFileDescriptorへの最後の参照がガベージコレクションされるまで、チャンネルは閉じられません。

また、CharBuffer CharsetDecoder.decode(ByteBuffer in)を認識していないようです。

あなたの質問は完全に無防備です。