博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java的NIO
阅读量:6900 次
发布时间:2019-06-27

本文共 13146 字,大约阅读时间需要 43 分钟。

JDK 1.4 的 java.nio.* 包中引入了新的Java I/O类库,其目的在于提高速度。

速度的提高在文件I/O和网络I/O中都有可能发生。
速度的提高来自于所使用的结构更接近于操作系统执行I/O的方式:通道缓冲器

import java.nio.*;import java.nio.channels.*;import java.io.*;public class GetChannel {    private static final int BSIZE = 1024;        @SuppressWarnings("resource")    public static void main(String[] args) throws Exception {        //旧I/O类库中有三个类被修改了,用以产生FileChannel。这三个被修改的类是FileInputStream、FileOutputStream以及RandomAccessFile        // Write a file:        FileChannel fc = new FileOutputStream("data.txt").getChannel();        fc.write(ByteBuffer.wrap("Some text ".getBytes()));        fc.close();        // Add to the end of the file:        fc = new RandomAccessFile("data.txt", "rw").getChannel();        fc.position(fc.size()); // Move to the end        fc.write(ByteBuffer.wrap("Some more".getBytes()));        fc.close();        // Read the file:        fc = new FileInputStream("data.txt").getChannel();        ByteBuffer buff = ByteBuffer.allocate(BSIZE);        fc.read(buff);        buff.flip();        while(buff.hasRemaining()){            System.out.print((char)buff.get());        }    }}
//简单的文件复制程序import java.nio.*;import java.nio.channels.*;import java.io.*;public class ChannelCopy {    private static final int BSIZE = 1024;        @SuppressWarnings("resource")    public static void main(String[] args) throws Exception {        if(args.length != 2) {            System.out.println("arguments: sourcefile destfile");            System.exit(1);        }        FileChannel in = new FileInputStream(args[0]).getChannel(), out = new FileOutputStream(args[1]).getChannel();        ByteBuffer buffer = ByteBuffer.allocate(BSIZE);        while(in.read(buffer) != -1) {            buffer.flip(); // Prepare for writing            out.write(buffer);            buffer.clear();  // Prepare for reading        }    }}
import java.nio.channels.*;import java.io.*;public class TransferTo {    @SuppressWarnings("resource")    public static void main(String[] args) throws Exception {        if(args.length != 2) {            System.out.println("arguments: sourcefile destfile");            System.exit(1);        }        FileChannel in = new FileInputStream(args[0]).getChannel(),                    out = new FileOutputStream(args[1]).getChannel();        in.transferTo(0, in.size(), out);        // Or:        // out.transferFrom(in, 0, in.size());    }}

1.转换数据

import java.nio.*;import java.nio.channels.*;import java.nio.charset.*;import java.io.*;public class BufferToText {    private static final int BSIZE = 1024;        @SuppressWarnings("resource")    public static void main(String[] args) throws Exception {        FileChannel fc = new FileOutputStream("data2.txt").getChannel();        fc.write(ByteBuffer.wrap("Some text".getBytes()));        fc.close();        fc = new FileInputStream("data2.txt").getChannel();        ByteBuffer buff = ByteBuffer.allocate(BSIZE);        fc.read(buff);        buff.flip();        // Doesn't work:        System.out.println(buff.asCharBuffer());                // Decode using this system's default Charset:        buff.rewind();        String encoding = System.getProperty("file.encoding");        System.out.println("Decoded using " + encoding + ": " + Charset.forName(encoding).decode(buff));                // Or, we could encode with something that will print:        fc = new FileOutputStream("data2.txt").getChannel();        fc.write(ByteBuffer.wrap("Some text".getBytes("UTF-16BE")));        fc.close();        // Now try reading again:        fc = new FileInputStream("data2.txt").getChannel();        buff.clear();        fc.read(buff);        buff.flip();        System.out.println(buff.asCharBuffer());                // Use a CharBuffer to write through:        fc = new FileOutputStream("data2.txt").getChannel();        buff = ByteBuffer.allocate(24); // More than needed        buff.asCharBuffer().put("Some text");        fc.write(buff);        fc.close();        // Read and display:        fc = new FileInputStream("data2.txt").getChannel();        buff.clear();        fc.read(buff);        buff.flip();        System.out.println(buff.asCharBuffer());    }}/*//输出卯浥?數Decoded using GBK: Some textSome textSome text*/

2.获取基本类型

import java.nio.*;public class GetData {    private static final int BSIZE = 1024;        public static void main(String[] args) {        ByteBuffer bb = ByteBuffer.allocate(BSIZE);        // Allocation automatically zeroes the ByteBuffer:        int i = 0;        while(i++ < bb.limit()){            if(bb.get() != 0){                System.out.println("nonzero");            }        }        System.out.println("i = " + i);                bb.rewind();        // Store and read a char array:        bb.asCharBuffer().put("Howdy!");        char c;        while((c = bb.getChar()) != 0){            System.out.print(c + " ");        }        System.out.println();                bb.rewind();        // Store and read a short:        bb.asShortBuffer().put((short)471142);        System.out.println(bb.getShort());                bb.rewind();        // Store and read an int:        bb.asIntBuffer().put(99471142);        System.out.println(bb.getInt());                bb.rewind();        // Store and read a long:        bb.asLongBuffer().put(99471142);        System.out.println(bb.getLong());                bb.rewind();        // Store and read a float:        bb.asFloatBuffer().put(99471142);        System.out.println(bb.getFloat());                bb.rewind();        // Store and read a double:        bb.asDoubleBuffer().put(99471142);        System.out.println(bb.getDouble());                bb.rewind();    }}/* Output:i = 1025H o w d y !1239099471142994711429.9471144E79.9471142E7*/

3.视图缓冲器

import java.nio.*;public class IntBufferDemo {    private static final int BSIZE = 1024;        public static void main(String[] args) {        ByteBuffer bb = ByteBuffer.allocate(BSIZE);        IntBuffer ib = bb.asIntBuffer();        // Store an array of int:        ib.put(new int[]{ 11, 42, 47, 99, 143, 811, 1016 });        // Absolute location read and write:        System.out.println(ib.get(3));        ib.put(3, 1811);        // Setting a new limit before rewinding the buffer.        ib.flip();        while(ib.hasRemaining()) {            int i = ib.get();            System.out.println(i);        }    }}/* Output:9911424718111438111016*/
import java.nio.*;public class ViewBuffers {        public static void main(String[] args) {        ByteBuffer bb = ByteBuffer.wrap(new byte[]{ 0, 0, 0, 0, 0, 0, 0, 'a' });        bb.rewind();        System.out.print("Byte Buffer ");        while(bb.hasRemaining()){            System.out.print(bb.position()+ " -> " + bb.get() + ", ");        }        System.out.println();                CharBuffer cb = ((ByteBuffer)bb.rewind()).asCharBuffer();        System.out.print("Char Buffer ");        while(cb.hasRemaining()){            System.out.print(cb.position() + " -> " + cb.get() + ", ");        }        System.out.println();                FloatBuffer fb = ((ByteBuffer)bb.rewind()).asFloatBuffer();        System.out.print("Float Buffer ");        while(fb.hasRemaining()){            System.out.print(fb.position()+ " -> " + fb.get() + ", ");        }        System.out.println();                IntBuffer ib = ((ByteBuffer)bb.rewind()).asIntBuffer();        System.out.print("Int Buffer ");        while(ib.hasRemaining()){            System.out.print(ib.position()+ " -> " + ib.get() + ", ");        }        System.out.println();                LongBuffer lb = ((ByteBuffer)bb.rewind()).asLongBuffer();        System.out.print("Long Buffer ");        while(lb.hasRemaining()){            System.out.print(lb.position()+ " -> " + lb.get() + ", ");        }        System.out.println();                ShortBuffer sb = ((ByteBuffer)bb.rewind()).asShortBuffer();        System.out.print("Short Buffer ");        while(sb.hasRemaining()){            System.out.print(sb.position()+ " -> " + sb.get() + ", ");        }        System.out.println();                DoubleBuffer db = ((ByteBuffer)bb.rewind()).asDoubleBuffer();        System.out.print("Double Buffer ");        while(db.hasRemaining()){            System.out.print(db.position()+ " -> " + db.get() + ", ");        }    }}/* Output:Byte Buffer 0 -> 0, 1 -> 0, 2 -> 0, 3 -> 0, 4 -> 0, 5 -> 0, 6 -> 0, 7 -> 97,Char Buffer 0 ->  , 1 ->  , 2 ->  , 3 -> a,Float Buffer 0 -> 0.0, 1 -> 1.36E-43,Int Buffer 0 -> 0, 1 -> 97,Long Buffer 0 -> 97,Short Buffer 0 -> 0, 1 -> 0, 2 -> 0, 3 -> 97,Double Buffer 0 -> 4.8E-322,*/

字节存放次序

import java.nio.*;import java.util.*;public class Endians {    public static void main(String[] args) {        ByteBuffer bb = ByteBuffer.wrap(new byte[12]);        bb.asCharBuffer().put("abcdef");        System.out.println(Arrays.toString(bb.array()));                bb.rewind();        bb.order(ByteOrder.BIG_ENDIAN);        bb.asCharBuffer().put("abcdef");        System.out.println(Arrays.toString(bb.array()));                bb.rewind();        bb.order(ByteOrder.LITTLE_ENDIAN);        bb.asCharBuffer().put("abcdef");        System.out.println(Arrays.toString(bb.array()));    }}/* Output:[0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102][0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102][97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0]*/

4.用缓冲器操纵数据

注意,ByteBuffer是将数据移进移出通道的唯一方式。

我们不能把基本类型的缓冲器转换成ByteBuffer,然而,我们可以经由视图缓冲器将基本类型数据移进移出ByteBuffer

5.缓冲器的细节

Buffer由数据和可以高效地访问及操纵这些数据的四个索引组成,这四个索引是:mark(标记)、position(位置)、limit(界限)和capacity(容量)。

1393432-20180602001918537-926861455.png

import java.nio.*;public class UsingBuffers {    //交换相邻字符    private static void symmetricScramble(CharBuffer buffer){        while(buffer.hasRemaining()) {            buffer.mark();            char c1 = buffer.get();            char c2 = buffer.get();            buffer.reset();            buffer.put(c2).put(c1);        }    }        public static void main(String[] args) {        char[] data = "UsingBuffers".toCharArray();        ByteBuffer bb = ByteBuffer.allocate(data.length * 2);        CharBuffer cb = bb.asCharBuffer();        cb.put(data);        System.out.println(cb.rewind());                symmetricScramble(cb);        System.out.println(cb.rewind());                symmetricScramble(cb);        System.out.println(cb.rewind());    }}/* Output:UsingBufferssUniBgfuefsrUsingBuffers*/

6.内存映射文件

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

import java.nio.*;import java.nio.channels.*;import java.io.*;public class LargeMappedFiles {    static int length = 0x8FFFFFF; // 128 MB    @SuppressWarnings("resource")    public static void main(String[] args) throws Exception {        MappedByteBuffer out = new RandomAccessFile("test.dat", "rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 0, length);        for(int i = 0; i < length; i++){            out.put((byte)'x');        }        System.out.println("Finished writing");        for(int i = length/2; i < length/2 + 6; i++){            System.out.print((char)out.get(i));        }    }}

7.文件加锁

JDK 1.4 引入了文件加锁机制,它允许我们同步访问某个作为共享资源的文件。

import java.nio.channels.*;import java.util.concurrent.*;import java.io.*;public class FileLocking {    public static void main(String[] args) throws Exception {        FileOutputStream fos= new FileOutputStream("file.txt");        FileLock fl = fos.getChannel().tryLock();        if(fl != null) {            System.out.println("Locked File");            TimeUnit.MILLISECONDS.sleep(100);            fl.release();            System.out.println("Released Lock");        }        fos.close();    }}

对映射文件的部分加锁

import java.nio.*;import java.nio.channels.*;import java.io.*;public class LockingMappedFiles {    static final int LENGTH = 0x8FFFFFF; // 128 MB    static FileChannel fc;        @SuppressWarnings("resource")    public static void main(String[] args) throws Exception {        fc = new RandomAccessFile("test.dat", "rw").getChannel();        MappedByteBuffer out = fc.map(FileChannel.MapMode.READ_WRITE, 0, LENGTH);        for(int i = 0; i < LENGTH; i++){            out.put((byte)'x');        }        new LockAndModify(out, 0, 0 + LENGTH/3);        new LockAndModify(out, LENGTH/2, LENGTH/2 + LENGTH/4);    }        private static class LockAndModify extends Thread {        private ByteBuffer buff;        private int start, end;        LockAndModify(ByteBuffer mbb, int start, int end) {            this.start = start;            this.end = end;            mbb.limit(end);            mbb.position(start);            buff = mbb.slice();            start();        }                public void run() {            try {                // Exclusive lock with no overlap:                FileLock fl = fc.lock(start, end, false);                System.out.println("Locked: "+ start +" to "+ end);                // Perform modification:                while(buff.position() < buff.limit() - 1){                    buff.put((byte)(buff.get() + 1));                }                fl.release();                System.out.println("Released: "+start+" to "+ end);            } catch(IOException e) {                throw new RuntimeException(e);            }        }    }}

参考资料:《Java编程思想》第18章 第10节

转载于:https://www.cnblogs.com/gzhjj/p/9123944.html

你可能感兴趣的文章
UIScrollView 拖动下拉 刷新
查看>>
基本数据类型课上练习
查看>>
我的第二个面试通知
查看>>
JavaScript 获取对象属性和方法
查看>>
完成任务
查看>>
javat Itext实践 pdf
查看>>
不能在此路径中使用此配置节。如果在父级别上锁定了该节,便会出现这种情况。锁定是默认设置的...
查看>>
结队编程第二次作业
查看>>
CentOS7.x 搭建 GitLab 教程
查看>>
动态Result配置
查看>>
如何通过trn日志文件恢复SQL Server 事务日志 还原 备份
查看>>
DAY3-“忙里偷闲”找你玩耍2018-1-11
查看>>
科目二考试标准操作要领
查看>>
磁盘性能测试学习之路1-认识磁盘的各项参数
查看>>
ubuntu用apt安装apache2时,出现E:未发现软件包 apache2
查看>>
POJ1251 Jungle Roads(Kruskal)(并查集)
查看>>
七牛,前端上传图片
查看>>
ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行
查看>>
qml 一个信号与多个方法关联 和 c++信号与槽类似写法
查看>>
简说Python生态系统的14年演变
查看>>