5
  Path file = Paths.get("c:/large.log");
  AsynchronousFileChannel channel = AsynchronousFileChannel.open(file);
  final ByteBuffer buffer = ByteBuffer.allocate(1000);
  channel.read(buffer, 0, buffer,
      new CompletionHandler<Integer, ByteBuffer>() {
        public void completed(Integer result, ByteBuffer attachment) {
          System.out.println(new String(buffer.array()));
        }
  }); 

このようにして、large.log から最初の 1000 バイトを読み取ることができます。ByteBuffer.allocate(1000*1000) のような大きなバイト配列を割り当てたくない場合、次のログを読むにはどうすればよいですか。これは OutOfMemory につながると思うからです。

誰かがサンプルコードを教えてくれますか? ありがとう。

ps:java.io.BufferedReader.read()の戻り値を確認できるので、JIOで大きなファイルをループ読みできます。しかし、NIO2 の扱い方がわかりません。

4

4 に答える 4

6

これが機能するハックです。

注意すべき点がいくつかあります。

  1. 出力にあなたbuffer.array()を使用しました。buffer.clear() を使用して位置をリセットし、非同期読み取りで 1000 のスペア バイトがあることを確認する必要がありましたが、配列から既存のデータが消去されません。その結果、ファイルの最後にいるときに、1000 バイト未満を読み取った場合、バッファー全体が出力されます。つまり、読み取った量に加えて、バッファーの最後にあったものの残りの 1000 バイトが出力されます。実生活では、それについて何かしたいと思うでしょう (おそらく、結果またはバッファーの位置を使用して)。
  2. 理由により、どのクラス変数がメソッドbuffer内で問題なく、どのクラス変数が null であるかを判断できませんでした。それがなぜなのかはまだわかりません。そこで、バッファではなく添付ファイルとして渡すように変更しました。それでも私には意味がありません。completedchannelchannel
  3. 非同期読み取りスレッドは、jvm の実行を維持するのに十分重要ではありません。readそのため、メイン メソッドの最後にa を追加しました。を押しEnterて終了します。
  4. クラス変数posは、読み取り元のファイル内の位置を維持します。
  5. メソッド中に別の非同期読み取りを開始すると、魔法が起こりますcomplete。これが、匿名クラスを破棄し、インターフェイス自体を実装した理由です。
  6. パスを自分のパスに戻す必要があります。

楽しむ。

import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;
import java.io.IOException;

public class TryNio implements CompletionHandler<Integer, AsynchronousFileChannel> {

       // need to keep track of the next position.
        int pos = 0;
        AsynchronousFileChannel channel =  null;
        ByteBuffer buffer = null;

        public void completed(Integer result, AsynchronousFileChannel attachment) {
                 // if result is -1 means nothing was read.
                if (result != -1) {
                        pos += result;  // don't read the same text again.
                                        // your output command.
                        System.out.println(new String(buffer.array()));

                        buffer.clear();  // reset the buffer so you can read more.
                }
                        // initiate another asynchronous read, with this.
                attachment.read(buffer, pos , attachment, this );


        }
        public void failed(Throwable exc,
                        AsynchronousFileChannel attachment) {
                System.err.println ("Error!");
                exc.printStackTrace();
        }

        public void doit() {
                Path file = Paths.get("/var/log/syslog");
                AsynchronousFileChannel channel =  null;
                try {
                        channel = AsynchronousFileChannel.open(file);
                } catch (IOException e) {
                        System.err.println ("Could not open file: " + file.toString());
                        System.exit(1); // yeah.  heh.
                }
                buffer = ByteBuffer.allocate(1000);

                 // start off the asynch read. 
                channel.read(buffer, pos , channel, this );
                // this method now exits, thread returns to main and waits for user input.
        }

        public static void main (String [] args) {
                TryNio tn = new TryNio();
                tn.doit();
             // wait fur user to press a key otherwise java exits because the 
             // asynch thread isn't important enough to keep it running.
                try { System.in.read(); } catch (IOException e) { }
        }
}
于 2013-10-23T05:15:44.707 に答える
0

ファイルに何か残っている場合は、completionHandler で別の読み取りを開始します。ただし、1000 よりもはるかに大きなバッファー、少なくとも 8192 を使用します。

于 2013-10-23T03:03:25.790 に答える