NIO

Java NIO教程
Java NIO之Selector(选择器)

例子

Channel Buffer:

private static void useNIO(){
    RandomAccessFile randomAccessFile = null;
    String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() +
            File.separator + "test.txt";
    Log.d(TAG, "zwm, filePath:" + filePath);
    FileChannel inChannel = null;
    try {
        randomAccessFile = new RandomAccessFile(new File(filePath), "rw");
        inChannel = randomAccessFile.getChannel();

        ByteBuffer byteBuffer = ByteBuffer.allocate(5);
        int byteReader = inChannel.read(byteBuffer);
        while (byteReader != -1) {
            Log.d(TAG, "zwm, byteReader: " + byteReader);

            byteBuffer.flip();

            while (byteBuffer.hasRemaining()) {
                Log.d(TAG, "zwm, get byteBuffer: " + (char)byteBuffer.get());
            }

            byteBuffer.clear();
            byteReader = inChannel.read(byteBuffer);
            Log.d(TAG, "zwm, byteReader again: " + byteReader);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            inChannel.close();
            randomAccessFile.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

//test.txt
1234567890

//输出
zwm, filePath:/storage/emulated/0/test.txt
zwm, byteReader: 5
zwm, get byteBuffer: 1
zwm, get byteBuffer: 2
zwm, get byteBuffer: 3
zwm, get byteBuffer: 4
zwm, get byteBuffer: 5
zwm, byteReader again: 5
zwm, byteReader: 5
zwm, get byteBuffer: 6
zwm, get byteBuffer: 7
zwm, get byteBuffer: 8
zwm, get byteBuffer: 9
zwm, get byteBuffer: 0
zwm, byteReader again: -1
private static void useNIO() {
    String newData = "New String to write to file..." + System.currentTimeMillis();

    ByteBuffer buf = ByteBuffer.allocate(48);
    buf.clear();
    buf.put(newData.getBytes());

    buf.flip();

    RandomAccessFile randomAccessFile = null;
    String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() +
            File.separator + "test.txt";
    Log.d(TAG, "zwm, filePath:" + filePath + ", file exist: " + new File(filePath).exists());
    FileChannel inChannel = null;
    try {
        randomAccessFile = new RandomAccessFile(new File(filePath), "rw");
        inChannel = randomAccessFile.getChannel();
        while(buf.hasRemaining()) {
            Log.d(TAG, "zwm, while loop");
            inChannel.write(buf);
        }

        Log.d(TAG, "zwm, position: " + inChannel.position());
        Log.d(TAG, "zwm, size: " + inChannel.size());

        inChannel.truncate(10);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            inChannel.close();
            randomAccessFile.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

//输出
zwm, filePath:/storage/emulated/0/test.txt, file exist: true
zwm, while loop
zwm, position: 43
zwm, size: 43

//test.txt
New String

Scattering Reads:

private static void useNIO(){
    RandomAccessFile randomAccessFile = null;
    String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() +
            File.separator + "test.txt";
    Log.d(TAG, "zwm, filePath:" + filePath);
    FileChannel inChannel = null;
    try {
        randomAccessFile = new RandomAccessFile(new File(filePath), "rw");
        inChannel = randomAccessFile.getChannel();
        ByteBuffer header = ByteBuffer.allocate(3);
        ByteBuffer body   = ByteBuffer.allocate(7);
        ByteBuffer[] bufferArray = { header, body };
        inChannel.read(bufferArray);
        header.flip();
        while (header.hasRemaining()) {
            Log.d(TAG, "zwm, get header: " +  (char)header.get());
        }
        body.flip();
        while (body.hasRemaining()) {
            Log.d(TAG, "zwm, get body: " +  (char)body.get());
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            inChannel.close();
            randomAccessFile.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

//test.txt
1234567890

//输出
zwm, filePath:/storage/emulated/0/test.txt
zwm, get header: 1
zwm, get header: 2
zwm, get header: 3
zwm, get body: 4
zwm, get body: 5
zwm, get body: 6
zwm, get body: 7
zwm, get body: 8
zwm, get body: 9
zwm, get body: 0

Gathering Writes:

private static void useNIO(){
    RandomAccessFile randomAccessFile = null;
    RandomAccessFile randomAccessFile2 = null;
    String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() +
            File.separator + "test.txt";
    String filePath2 = Environment.getExternalStorageDirectory().getAbsolutePath() +
            File.separator + "test2.txt";
    Log.d(TAG, "zwm, filePath:" + filePath + ", file exist: " + new File(filePath).exists());
    Log.d(TAG, "zwm, filePath2:" + filePath2 + ", file exist: " + new File(filePath2).exists());
    FileChannel inChannel = null;
    FileChannel inChannel2 = null;
    try {
        randomAccessFile = new RandomAccessFile(new File(filePath), "rw");
        randomAccessFile2 = new RandomAccessFile(new File(filePath2), "rw");
        inChannel = randomAccessFile.getChannel();
        inChannel2 = randomAccessFile2.getChannel();
        ByteBuffer header = ByteBuffer.allocate(3);
        ByteBuffer body   = ByteBuffer.allocate(7);
        ByteBuffer[] bufferArray = { header, body };
        inChannel.read(bufferArray);
        header.flip();
        while (header.hasRemaining()) {
            Log.d(TAG, "zwm, get header: " +  (char)header.get());
        }
        body.flip();
        while (body.hasRemaining()) {
            Log.d(TAG, "zwm, get body: " +  (char)body.get());
        }

        header.flip();
        body.flip();
        ByteBuffer[] bufferArray2 = { body, header };
        inChannel2.write(bufferArray2);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            inChannel2.close();
            inChannel.close();
            randomAccessFile2.close();
            randomAccessFile.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

//test.txt
1234567890

//输出
zwm, filePath:/storage/emulated/0/test.txt, file exist: true
zwm, filePath2:/storage/emulated/0/test2.txt, file exist: true
zwm, get header: 1
zwm, get header: 2
zwm, get header: 3
zwm, get body: 4
zwm, get body: 5
zwm, get body: 6
zwm, get body: 7
zwm, get body: 8
zwm, get body: 9
zwm, get body: 0

//test2.txt
4567890123

FileChannel#transferFrom():

private static void useNIO(){
    RandomAccessFile randomAccessFile = null;
    RandomAccessFile randomAccessFile2 = null;
    String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() +
            File.separator + "test.txt";
    String filePath2 = Environment.getExternalStorageDirectory().getAbsolutePath() +
            File.separator + "test2.txt";
    Log.d(TAG, "zwm, filePath:" + filePath + ", file exist: " + new File(filePath).exists());
    Log.d(TAG, "zwm, filePath2:" + filePath2 + ", file exist: " + new File(filePath2).exists());
    FileChannel inChannel = null;
    FileChannel inChannel2 = null;
    try {
        randomAccessFile = new RandomAccessFile(new File(filePath), "rw");
        randomAccessFile2 = new RandomAccessFile(new File(filePath2), "rw");
        inChannel = randomAccessFile.getChannel();
        inChannel2 = randomAccessFile2.getChannel();
        long position = 0;
        long count = inChannel.size();
        inChannel2.transferFrom(inChannel, position, count);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            inChannel2.close();
            inChannel.close();
            randomAccessFile2.close();
            randomAccessFile.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

//test.txt
1234567890

//test2.txt
1234567890

FileChannel#transferTo():

private static void useNIO(){
    RandomAccessFile randomAccessFile = null;
    RandomAccessFile randomAccessFile2 = null;
    String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() +
            File.separator + "test.txt";
    String filePath2 = Environment.getExternalStorageDirectory().getAbsolutePath() +
            File.separator + "test2.txt";
    Log.d(TAG, "zwm, filePath:" + filePath + ", file exist: " + new File(filePath).exists());
    Log.d(TAG, "zwm, filePath2:" + filePath2 + ", file exist: " + new File(filePath2).exists());
    FileChannel inChannel = null;
    FileChannel inChannel2 = null;
    try {
        randomAccessFile = new RandomAccessFile(new File(filePath), "rw");
        randomAccessFile2 = new RandomAccessFile(new File(filePath2), "rw");
        inChannel = randomAccessFile.getChannel();
        inChannel2 = randomAccessFile2.getChannel();
        long position = 0;
        long count = inChannel.size();
        inChannel.transferTo(position, count, inChannel2);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            inChannel2.close();
            inChannel.close();
            randomAccessFile2.close();
            randomAccessFile.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

//test.txt
1234567890

//test2.txt
1234567890

ServerSocketChannel SocketChannel 阻塞模式:

private static void useNIO() {
    initServerSocketChannel();

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "zwm, delay end");
            initSocketChannel();
        }
    }, 5000);

}

private static void initServerSocketChannel() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "zwm, initServerSocketChannel, thread: " + Thread.currentThread().getName());
            ServerSocketChannel serverSocketChannel = null;
            SocketChannel socketChannel = null;
            try {
                serverSocketChannel = ServerSocketChannel.open();
                serverSocketChannel.socket().bind(new InetSocketAddress(9999));
                while(true){
                    Log.d(TAG, "zwm, ServerSocketChannel accept start");
                    socketChannel =
                            serverSocketChannel.accept();
                    Log.d(TAG, "zwm, ServerSocketChannel accept end");

                    String newData = "New String to write to file...";

                    //生成Buffer,并向Buffer中写数据
                    ByteBuffer buf = ByteBuffer.allocate(48);
                    buf.clear();
                    buf.put(newData.getBytes());

                    //切换buffer为读模式
                    buf.flip();

                    while(buf.hasRemaining()) {
                        Log.d(TAG, "zwm, server write start");
                        socketChannel.write(buf);
                        Log.d(TAG, "zwm, server write end");
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    socketChannel.close();
                    serverSocketChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();
}

private static void initSocketChannel() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "zwm, initSocketChannel, thread: " + Thread.currentThread().getName());
            SocketChannel socketChannel = null;
            try {
                socketChannel = SocketChannel.open();
                Log.d(TAG, "zwm, client connect start");
                socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999));
                Log.d(TAG, "zwm, client connect end");

                ByteBuffer byteBuffer = ByteBuffer.allocate(48);
                Log.d(TAG, "zwm, client read start");
                int byteReader = socketChannel.read(byteBuffer);
                Log.d(TAG, "zwm, client read end");
                while (byteReader != -1) {
                    Log.d(TAG, "zwm, byteReader: " + byteReader);

                    byteBuffer.flip();

                    while (byteBuffer.hasRemaining()) {
                        Log.d(TAG, "zwm, get byteBuffer: " + (char)byteBuffer.get());
                    }

                    byteBuffer.clear();
                    byteReader = socketChannel.read(byteBuffer);
                    Log.d(TAG, "zwm, byteReader again: " + byteReader);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    socketChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }).start();
}

//输出
zwm, initServerSocketChannel, thread: Thread-7
zwm, ServerSocketChannel accept start
zwm, delay end
zwm, initSocketChannel, thread: Thread-8
zwm, client connect start
zwm, client connect end
zwm, client read start
zwm, ServerSocketChannel accept end
zwm, server write start
zwm, server write end
zwm, client read end
zwm, ServerSocketChannel accept start
zwm, byteReader: 30
zwm, get byteBuffer: N
zwm, get byteBuffer: e
zwm, get byteBuffer: w
zwm, get byteBuffer:  
zwm, get byteBuffer: S
zwm, get byteBuffer: t
zwm, get byteBuffer: r
zwm, get byteBuffer: i
zwm, get byteBuffer: n
zwm, get byteBuffer: g
zwm, get byteBuffer:  
zwm, get byteBuffer: t
zwm, get byteBuffer: o
zwm, get byteBuffer:  
zwm, get byteBuffer: w
zwm, get byteBuffer: r
zwm, get byteBuffer: i
zwm, get byteBuffer: t
zwm, get byteBuffer: e
zwm, get byteBuffer:  
zwm, get byteBuffer: t
zwm, get byteBuffer: o
zwm, get byteBuffer:  
zwm, get byteBuffer: f
zwm, get byteBuffer: i
zwm, get byteBuffer: l
zwm, get byteBuffer: e
zwm, get byteBuffer: .
zwm, get byteBuffer: .
zwm, get byteBuffer: .

ServerSocketChannel SocketChannel 非阻塞模式:

private static void useNIO() {
    initServerSocketChannel();

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "zwm, delay end");
            initSocketChannel();
        }
    }, 5000);

}

private static void initServerSocketChannel() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "zwm, initServerSocketChannel, thread: " + Thread.currentThread().getName());
            ServerSocketChannel serverSocketChannel = null;
            SocketChannel socketChannel = null;
            try {
                serverSocketChannel = ServerSocketChannel.open();
                serverSocketChannel.socket().bind(new InetSocketAddress(9999));
                serverSocketChannel.configureBlocking(false); //配置ServerSocketChannel为非阻塞模式
                while(true){
                    //Log.d(TAG, "zwm, ServerSocketChannel accept start");
                    socketChannel = serverSocketChannel.accept();
                    //Log.d(TAG, "zwm, ServerSocketChannel accept end, socketChannel: " + socketChannel);

                    while(socketChannel != null) { //需要判断是否为空
                        socketChannel.configureBlocking(false); //配置SocketChannel为非阻塞模式

                        String newData = "New String to write to file...";

                        //生成Buffer,并向Buffer中写数据
                        ByteBuffer buf = ByteBuffer.allocate(48);
                        buf.clear();
                        buf.put(newData.getBytes());

                        //切换buffer为读模式
                        buf.flip();

                        while (buf.hasRemaining()) {
                            Log.d(TAG, "zwm, server write start");
                            socketChannel.write(buf);
                            Log.d(TAG, "zwm, server write end");
                        }

                        return;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    socketChannel.close();
                    serverSocketChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();
}

private static void initSocketChannel() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "zwm, initSocketChannel, thread: " + Thread.currentThread().getName());
            SocketChannel socketChannel = null;
            try {
                socketChannel = SocketChannel.open();
                socketChannel.configureBlocking(false); //配置SocketChannel为非阻塞模式
                Log.d(TAG, "zwm, client connect start");
                socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999));
                Log.d(TAG, "zwm, client connect end");

                while(!socketChannel.finishConnect() ) { //需要判断是否完成连接

                }

                Log.d(TAG, "zwm, SocketChannel finish connect");
                ByteBuffer byteBuffer = ByteBuffer.allocate(48);
                Log.d(TAG, "zwm, client read start");
                int byteReader = socketChannel.read(byteBuffer);
                Log.d(TAG, "zwm, client read end");
                while (byteReader != -1) {
                    Log.d(TAG, "zwm, byteReader: " + byteReader);

                    byteBuffer.flip();

                    while (byteBuffer.hasRemaining()) {
                        Log.d(TAG, "zwm, get byteBuffer: " + (char) byteBuffer.get());
                    }

                    byteBuffer.clear();
                    byteReader = socketChannel.read(byteBuffer);
                    Log.d(TAG, "zwm, byteReader again: " + byteReader);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    socketChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }).start();
}

//输出
zwm, initServerSocketChannel, thread: Thread-7
zwm, delay end
zwm, initSocketChannel, thread: Thread-8
zwm, client connect start
zwm, client connect end
zwm, SocketChannel finish connect
zwm, client read start
zwm, server write start
zwm, client read end
zwm, byteReader: 0
zwm, server write end
zwm, byteReader again: 30
zwm, byteReader: 30
zwm, get byteBuffer: N
zwm, get byteBuffer: e
zwm, get byteBuffer: w
zwm, get byteBuffer:  
zwm, get byteBuffer: S
zwm, get byteBuffer: t
zwm, get byteBuffer: r
zwm, get byteBuffer: i
zwm, get byteBuffer: n
zwm, get byteBuffer: g
zwm, get byteBuffer:  
zwm, get byteBuffer: t
zwm, get byteBuffer: o
zwm, get byteBuffer:  
zwm, get byteBuffer: w
zwm, get byteBuffer: r
zwm, get byteBuffer: i
zwm, get byteBuffer: t
zwm, get byteBuffer: e
zwm, get byteBuffer:  
zwm, get byteBuffer: t
zwm, get byteBuffer: o
zwm, get byteBuffer:  
zwm, get byteBuffer: f
zwm, get byteBuffer: i
zwm, get byteBuffer: l
zwm, get byteBuffer: e
zwm, get byteBuffer: .
zwm, get byteBuffer: .
zwm, get byteBuffer: .
zwm, byteReader again: -1

Selector:

private static void useNIO() {
    initServerSocketChannel();

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "zwm, delay end");
            initSocketChannel();
        }
    }, 5000);

}

private static void initServerSocketChannel() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "zwm, initServerSocketChannel, thread: " + Thread.currentThread().getName());
            try {
                ServerSocketChannel ssc = ServerSocketChannel.open();
                ssc.socket().bind(new InetSocketAddress("127.0.0.1", 9999));
                ssc.configureBlocking(false);

                Selector selector = Selector.open();
                // 注册 channel,并且指定感兴趣的事件是 Accept
                ssc.register(selector, SelectionKey.OP_ACCEPT);

                ByteBuffer readBuff = ByteBuffer.allocate(1024);
                ByteBuffer writeBuff = ByteBuffer.allocate(128);
                writeBuff.put("From server".getBytes());

                while (true) {
                    int ready = selector.select();
                    Log.d(TAG, "zwm, ready: " + ready);

                    Set<SelectionKey> keys = selector.selectedKeys();
                    Iterator<SelectionKey> it = keys.iterator();
                    while (it.hasNext()) {
                        SelectionKey key = it.next();
                        it.remove();

                        if (key.isAcceptable()) {
                            Log.d(TAG, "zwm, isAcceptable");
                            // 创建新的连接,并且把连接注册到selector上,而且,
                            // 声明这个channel只对读操作感兴趣。
                            SocketChannel socketChannel = ssc.accept();
                            socketChannel.configureBlocking(false);
                            socketChannel.register(selector, SelectionKey.OP_READ);
                        }
                        else if (key.isReadable()) {
                            Log.d(TAG, "zwm, isReadable");
                            SocketChannel socketChannel = (SocketChannel) key.channel();
                            readBuff.clear();
                            socketChannel.read(readBuff);
                            readBuff.flip();
                            while (readBuff.hasRemaining()) {
                                Log.d(TAG, "zwm, server get readBuff: " + (char) readBuff.get());
                            }
                            key.interestOps(SelectionKey.OP_WRITE);
                        }
                        else if (key.isWritable()) {
                            Log.d(TAG, "zwm, isWritable");
                            writeBuff.flip();
                            SocketChannel socketChannel = (SocketChannel) key.channel();
                            socketChannel.write(writeBuff);
                            key.interestOps(SelectionKey.OP_READ);
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }).start();
}

private static void initSocketChannel() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "zwm, initSocketChannel, thread: " + Thread.currentThread().getName());
            try {
                SocketChannel socketChannel = SocketChannel.open();
                socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999));

                ByteBuffer writeBuffer = ByteBuffer.allocate(32);
                ByteBuffer readBuffer = ByteBuffer.allocate(32);

                writeBuffer.put("From client".getBytes());
                writeBuffer.flip();
                socketChannel.write(writeBuffer);

                readBuffer.clear();
                socketChannel.read(readBuffer);
                readBuffer.flip();
                while (readBuffer.hasRemaining()) {
                    Log.d(TAG, "zwm, client get readBuffer: " + (char) readBuffer.get());
                }
            } catch (IOException e) {
            }
        }
    }).start();
}

//输出
zwm, initServerSocketChannel, thread: Thread-7
zwm, delay end
zwm, initSocketChannel, thread: Thread-8
zwm, ready: 1
zwm, isAcceptable
zwm, ready: 1
zwm, isReadable
zwm, server get readBuff: F
zwm, server get readBuff: r
zwm, server get readBuff: o
zwm, server get readBuff: m
zwm, server get readBuff:  
zwm, server get readBuff: c
zwm, server get readBuff: l
zwm, server get readBuff: i
zwm, server get readBuff: e
zwm, server get readBuff: n
zwm, server get readBuff: t
zwm, ready: 1
zwm, isWritable
zwm, client get readBuffer: F
zwm, client get readBuffer: r
zwm, client get readBuffer: o
zwm, client get readBuffer: m
zwm, client get readBuffer:  
zwm, client get readBuffer: s
zwm, client get readBuffer: e
zwm, client get readBuffer: r
zwm, client get readBuffer: v
zwm, client get readBuffer: e
zwm, client get readBuffer: r

DatagramChannel:

private static void useNIO() {
    initServerSocketChannel();

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "zwm, delay end");
            initSocketChannel();
        }
    }, 5000);

}

private static void initServerSocketChannel() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "zwm, initServerSocketChannel, thread: " + Thread.currentThread().getName());
            try {
                DatagramChannel channel = DatagramChannel.open();
                channel.socket().bind(new InetSocketAddress(9999));

                ByteBuffer buf = ByteBuffer.allocate(48);
                buf.clear();
                channel.receive(buf);

                buf.flip();
                while (buf.hasRemaining()) {
                    Log.d(TAG, "zwm, server get buf: " + (char) buf.get());
                }
            } catch (SocketException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }).start();
}

private static void initSocketChannel() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "zwm, initSocketChannel, thread: " + Thread.currentThread().getName());
            try {
                DatagramChannel channel = DatagramChannel.open();

                String newData = "New String to write to file";
                ByteBuffer buf = ByteBuffer.allocate(48);
                buf.clear();
                buf.put(newData.getBytes());
                buf.flip();
                int bytesSent = channel.send(buf, new InetSocketAddress("127.0.0.1", 9999));
                Log.d(TAG, "zwm, client bytesSent: " + bytesSent);
            } catch (SocketException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }).start();
}

//输出
zwm, initServerSocketChannel, thread: Thread-7
zwm, delay end
zwm, initSocketChannel, thread: Thread-8
zwm, server get buf: N
zwm, server get buf: e
zwm, server get buf: w
zwm, server get buf:  
zwm, server get buf: S
zwm, server get buf: t
zwm, server get buf: r
zwm, server get buf: i
zwm, server get buf: n
zwm, server get buf: g
zwm, server get buf:  
zwm, server get buf: t
zwm, server get buf: o
zwm, server get buf:  
zwm, server get buf: w
zwm, server get buf: r
zwm, server get buf: i
zwm, server get buf: t
zwm, server get buf: e
zwm, server get buf:  
zwm, server get buf: t
zwm, server get buf: o
zwm, server get buf:  
zwm, server get buf: f
zwm, server get buf: i
zwm, server get buf: l
zwm, server get buf: e
zwm, client bytesSent: 27

Pipe:

private static void useNIO() {
    try {
        Pipe pipe = Pipe.open();

        Pipe.SinkChannel sinkChannel = pipe.sink();
        String newData = "New String to write to file";
        ByteBuffer writeBuffer = ByteBuffer.allocate(48);
        writeBuffer.clear();
        writeBuffer.put(newData.getBytes());
        writeBuffer.flip();
        while(writeBuffer.hasRemaining()) {
            sinkChannel.write(writeBuffer);
        }

        Pipe.SourceChannel sourceChannel = pipe.source();
        ByteBuffer readBuffer = ByteBuffer.allocate(48);
        int bytesRead = sourceChannel.read(readBuffer);
        Log.d(TAG, "zwm, bytesRead: " + bytesRead);
        readBuffer.flip();
        while (readBuffer.hasRemaining()) {
            Log.d(TAG, "zwm, get readBuffer: " + (char) readBuffer.get());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

//输出
zwm, bytesRead: 27
zwm, get readBuffer: N
zwm, get readBuffer: e
zwm, get readBuffer: w
zwm, get readBuffer:  
zwm, get readBuffer: S
zwm, get readBuffer: t
zwm, get readBuffer: r
zwm, get readBuffer: i
zwm, get readBuffer: n
zwm, get readBuffer: g
zwm, get readBuffer:  
zwm, get readBuffer: t
zwm, get readBuffer: o
zwm, get readBuffer:  
zwm, get readBuffer: w
zwm, get readBuffer: r
zwm, get readBuffer: i
zwm, get readBuffer: t
zwm, get readBuffer: e
zwm, get readBuffer:  
zwm, get readBuffer: t
zwm, get readBuffer: o
zwm, get readBuffer:  
zwm, get readBuffer: f
zwm, get readBuffer: i
zwm, get readBuffer: l
zwm, get readBuffer: e

产生可写的、可读可写的及可读的通道:

String fileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "IOTest.txt";
String filePath = fileDir + File.separator + fileName;
String fileNameOutput = "IOTestOutput.txt";
String filePathOutput = fileDir + File.separator + fileNameOutput;
boolean fileExist = new File(filePath).exists();
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);

//可写的通道
try {
    FileChannel fc = new FileOutputStream(filePath).getChannel();
    fc.write(ByteBuffer.wrap("Some text".getBytes()));
} catch (IOException e) {
    e.printStackTrace();
}

//IOTest.txt
Some text

//可读可写的通道
try {
    FileChannel fc = new RandomAccessFile(filePath, "rw").getChannel();
    fc.position(fc.size()); //Move to the end
    fc.write(ByteBuffer.wrap("Some more".getBytes()));

} catch (IOException e) {
    e.printStackTrace();
}

//IOTest.txt
Some textSome text

//可读的通道
try {
    FileChannel fc = new FileInputStream(filePath).getChannel();
    ByteBuffer buff = ByteBuffer.allocate(1024);
    fc.read(buff);
    buff.flip();
    while(buff.hasRemaining()) {
        Log.d(TAG, "zwm, char: " + (char)buff.get());
    }
} catch (IOException e) {
    e.printStackTrace();
}

//输出
zwm, filePath: /storage/emulated/0/IOTest.txt, fileExist: true
zwm, char: S
zwm, char: o
zwm, char: m
zwm, char: e
zwm, char:  
zwm, char: t
zwm, char: e
zwm, char: x
zwm, char: t
zwm, char: S
zwm, char: o
zwm, char: m
zwm, char: e
zwm, char:  
zwm, char: m
zwm, char: o
zwm, char: r
zwm, char: e

简单文件复制程序(不推荐):

String fileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "IOTest.txt";
String filePath = fileDir + File.separator + fileName;
String fileNameOutput = "IOTestOutput.txt";
String filePathOutput = fileDir + File.separator + fileNameOutput;
boolean fileExist = new File(filePath).exists();
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);

try {
    FileChannel in = new FileInputStream(filePath).getChannel();
    FileChannel out = new FileOutputStream(filePathOutput).getChannel();
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    while(in.read(buffer) != -1) {
        buffer.flip();
        out.write(buffer);
        buffer.clear();
    }
} catch (IOException e) {
    e.printStackTrace();
}

//IOTest.txt
Some textSome text

//IOTestOutput.txt
Some textSome text

将一个通道和另一个通道直接相连(推荐):

try {
    FileChannel in = new FileInputStream(filePath).getChannel();
    FileChannel out = new FileOutputStream(filePathOutput).getChannel();
    //in.transferTo(0, in.size(), out); //方法1
    out.transferFrom(in, 0, in.size()); //方法2
} catch (IOException e) {
    e.printStackTrace();
}

//IOTest.txt
Some textSome text

//IOTestOutput.txt
Some textSome text

转换数据:

String fileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "IOTest.txt";
String filePath = fileDir + File.separator + fileName;
String fileNameOutput = "IOTestOutput.txt";
String filePathOutput = fileDir + File.separator + fileNameOutput;
boolean fileExist = new File(filePath).exists();
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);

try {
    FileChannel fc = new FileInputStream(filePath).getChannel();
    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
    fc.read(byteBuffer);
    byteBuffer.flip();

    //不起作用,输出乱码
    Log.d(TAG, "zwm, output: " + byteBuffer.asCharBuffer());

    //方法1,输出解码
    byteBuffer.rewind();
    String encoding = System.getProperty("file.encoding");
    Log.d(TAG, "zwm, encoding: " + encoding);
    CharBuffer charBuffer = Charset.forName(encoding).decode(byteBuffer);
    Log.d(TAG, "zwm, method 1, output: " + charBuffer);

    //方法2,输入编码,输出转换
    fc = new FileOutputStream(filePath).getChannel();
    fc.write(ByteBuffer.wrap("Some text".getBytes("UTF-16BE")));
    fc.close();
    fc = new FileInputStream(filePath).getChannel();
    byteBuffer.clear();
    fc.read(byteBuffer);
    byteBuffer.flip();
    Log.d(TAG, "zwm, method 2, output: " + byteBuffer.asCharBuffer());

    //方法3,输入转换,输出转换
    fc = new FileOutputStream(filePath).getChannel();
    byteBuffer = ByteBuffer.allocate(24); //More than needed
    byteBuffer.asCharBuffer().put("Some text");
    fc.write(byteBuffer);
    fc.close();
    fc = new FileInputStream(filePath).getChannel();
    byteBuffer.clear();
    fc.read(byteBuffer);
    byteBuffer.flip();
    Log.d(TAG, "zwm, method 3, output: " + byteBuffer.asCharBuffer());
} catch (IOException e) {
    e.printStackTrace();
}

//IOTest.txt
Some text

//输出
zwm, filePath: /storage/emulated/0/IOTest.txt, fileExist: true
zwm, output: 卯浥?數
zwm, encoding: UTF-8
zwm, method 1, output: Some text
zwm, method 2, output: Some text
zwm, method 3, output: Some text??????

获取基本类型:

ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
int i = 0;
while(i++ < byteBuffer.limit()) {
    if(byteBuffer.get() != 0) {
        Log.d(TAG, "zwm, nonzero");
    }
}
Log.d(TAG, "zwm, i: " + i);
byteBuffer.rewind();

byteBuffer.asCharBuffer().put("Howdy!");
char c;
while ((c = byteBuffer.getChar()) != 0) {
    Log.d(TAG, "zwm, char: " + c);
}
byteBuffer.rewind();

byteBuffer.asShortBuffer().put((short)471142);
Log.d(TAG, "zwm, short: " + byteBuffer.getShort());
byteBuffer.rewind();

byteBuffer.asIntBuffer().put(99471142);
Log.d(TAG, "zwm, int: " + byteBuffer.getInt());
byteBuffer.rewind();

byteBuffer.asLongBuffer().put(99471142);
Log.d(TAG, "zwm, long: " + byteBuffer.getLong());
byteBuffer.rewind();

byteBuffer.asFloatBuffer().put(99471142);
Log.d(TAG, "zwm, float: " + byteBuffer.getFloat());
byteBuffer.rewind();

byteBuffer.asDoubleBuffer().put(99471142);
Log.d(TAG, "zwm, double: " + byteBuffer.getDouble());
byteBuffer.rewind();

//输出
zwm, i: 1025
zwm, char: H
zwm, char: o
zwm, char: w
zwm, char: d
zwm, char: y
zwm, char: !
zwm, short: 12390
zwm, int: 99471142
zwm, long: 99471142
zwm, float: 9.9471144E7
zwm, double: 9.9471142E7

内存映射文件:
内存映射文件允许我们创建和修改那些因为太大而不能放入内存的文件。

String fileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "IOTest.txt";
String filePath = fileDir + File.separator + fileName;
String fileNameOutput = "IOTestOutput.txt";
String filePathOutput = fileDir + File.separator + fileNameOutput;
boolean fileExist = new File(filePath).exists();
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);

int length = (int)new File(filePath).length();
Log.d(TAG, "zwm, file length: " + length);
try {
    MappedByteBuffer out = new RandomAccessFile(filePath, "rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 0, length);
    for(int i=0; i<length; i++) {
        out.put((byte)'x'); //写操作
    }
    Log.d(TAG, "zwm, Finished writing");
    for(int i=0; i<length; i++) {
        Log.d(TAG, "zwm, char: " + (char)out.get(i)); //读操作
    }
} catch (IOException e) {
    e.printStackTrace();
}

//输出
zwm, filePath: /storage/emulated/0/IOTest.txt, fileExist: true
zwm, file length: 24
zwm, Finished writing
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x
zwm, char: x

文件加锁:
JDK1.4引入了文件加锁机制,它允许我们同步访问某个作为共享资源的文件。
文件锁对其他的操作系统进程是可见的,因为Java的文件加锁直接映射到了本地操作系统的加锁工具。
相关方法:

tryLock() //非阻塞式,它设法获取锁,如果不能获得(当其他一些进程已经持有相同的锁,并且不共享时),它将直接从方法调用返回
tryLock(long position, long size, boolean shared) //对文件的一部分上锁,加锁区域为从position到position+size,shared指定释放是否是共享锁
lock() //阻塞式,它要阻塞进程直至锁可以获得,或调用lock()的线程中断,或调用lock()的通道关闭
lock(long position, long size, boolean shared) //对文件的一部分上锁,加锁区域为从position到position+size,shared指定释放是否是共享锁
release() //释放锁
isShared() //是否为共享锁

无参数的加锁方法会对整个文件进行加锁,文件变大后也是如此。
有参数的加锁方法会对文件的固定区域加锁,文件变大后也是如此。
对独占锁或者共享锁的支持必须由底层的操作系统提供,如果操作系统不支持共享锁并为每一个请求都创建一个锁,那么它就会使用独占锁。

文件加锁简单例子:

String fileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "IOTest.txt";
String filePath = fileDir + File.separator + fileName;
String fileNameOutput = "IOTestOutput.txt";
String filePathOutput = fileDir + File.separator + fileNameOutput;
boolean fileExist = new File(filePath).exists();
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);

try {
    FileOutputStream fos = new FileOutputStream(filePath);
    FileLock fl = fos.getChannel().tryLock();
    if(fl != null) {
        Log.d(TAG, "zwm, Locked File");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        fl.release();
        Log.d(TAG, "zwm, Released Lock");
    }
    fos.close();
} catch (IOException e) {
    e.printStackTrace();
}

//输出
zwm, filePath: /storage/emulated/0/IOTest.txt, fileExist: true
zwm, Locked File
zwm, Released Lock

对映射文件的部分加锁:

public class LockAndModify extends Thread {
    private FileChannel fc;
    private ByteBuffer buff;
    private int start, end;
    public LockAndModify(FileChannel fc, ByteBuffer mob, int start, int end) {
        this.fc = fc;
        this.start = start;
        this.end = end;
        mob.limit(end);
        mob.position(start);
        buff = mob.slice();
        start();
    }
    public void run() {
        try {
            Log.d(TAG, "zwm, Locked: " + start + " to " + end);
            FileLock fl = fc.lock(start, end, false);
            Log.d(TAG, "zwm, buff position: " + buff.position() + ", buff limit: " + buff.limit());
            while(buff.position() < buff.limit()) {
                Log.d(TAG, "zwm, buff position: " + buff.position());
                buff.put((byte) 'k');
            }
            fl.release();
           Log.d(TAG, "zwm, Release: " + start + " to " + end);
        } catch (IOException e) {
            e.printStackTrace();
            Log.d(TAG, "zwm, IOException");
        }
    }
}


//测试代码
String fileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "IOTest.txt";
final String filePath = fileDir + File.separator + fileName;
String fileNameOutput = "IOTestOutput.txt";
String filePathOutput = fileDir + File.separator + fileNameOutput;
boolean fileExist = new File(filePath).exists();
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);

try {
    final int length = (int)new File(filePath).length();
    Log.d(TAG, "zwm, length: " + length);
    FileChannel fc = new RandomAccessFile(filePath, "rw").getChannel();
    final MappedByteBuffer out = fc.map(FileChannel.MapMode.READ_WRITE, 0, length);
    for(int i=0; i<length; i++) {
        out.put((byte)'e'); //写操作
    }

    new LockAndModify(fc, out, 0, 0+length/3); //部分加锁
    new LockAndModify(fc, out, length/2, length/2+length/4); //部分加锁
} catch (IOException e) {
    e.printStackTrace();
    Log.d(TAG, "zwm, IOException");
}

//输出
zwm, filePath: /storage/emulated/0/IOTest.txt, fileExist: true
zwm, length: 9
zwm, Locked: 4 to 6
zwm, Locked: 0 to 3
zwm, buff position: 0, buff limit: 3
zwm, buff position: 0
zwm, buff position: 1
zwm, buff position: 2
zwm, Release: 0 to 3
zwm, buff position: 0, buff limit: 2
zwm, buff position: 0
zwm, buff position: 1
zwm, Release: 4 to 6

//IOTest.txt
kkkekkeee
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容