Path
- Path表示文件路径/文件
- 创建方法
- Paths的static方法//实际上底层调用了FileSystems.getDefault().getPath()方法
- Path path = Paths.get(String first, String… more);
- Path path = Paths.get(URI uri); //URI uri = URI.create(“C://ssssss”);
- FIleSystems方法
- Path path = FileSystems.getDefault().getPath(“C://ssss”);
- Paths的static方法//实际上底层调用了FileSystems.getDefault().getPath()方法
I/O
- 分类
- 按操作方式
- 按操作对象
- 按操作方式
- 其他
- File
- 代表磁盘文件本身的对象
- 构造方法:File(String pathName),pathName是文件路径
- RandomAccessFile类
- 是Object的子类
- 随机访问:可以跳转到文件任意位置读写数据
- 位置指示器:当前读写的位置
- 构造方法RandomAccessFile(File file/String name, String mode)
- mode
- r:只读
- rw:读写
- rwd:读写,每次对文件内容的更新都写入底层存储设备
- rws:读写,每次对文件内容/元数据的更新都写入底层存储设备
- 用完需要close()
- File
NI/O
- Non-Blocking I/O, 面向缓冲,基于通道.通过内存映射文件(将文件的一段区域映射到内存中)
三大组件
Buffer缓冲区
- 本质上是一块内存区
- 能发送基本类型(ByteBuffer/CharBuffer/ShortBuffer/IntBuffer/LongBuffer/FloatBuffer/DoubleBuffer)
步骤
数据写入buffer
ByteBuffer buffer = ByteBuffer.allocate(1024); buffer.put("abc".getByte());
调用flip
buffer.flip();
从buffer中读取数据
char a = (char)buffer.get(); char b = (char)buffer.get(); char c = (char)buffer.get();
调用buffer.clear()/buffer.compact()
buffer.clear();
方法 描述 buffer(int mark, int position, int limit, int capacity) 记忆标志位,下一个读写位置,有效位数,容量 mark() 取当前的position快照标记mark position(int position) 设置position的位置 limit(int limit) 如果position>limit,position=limit.如果mark>limit,重置mark reset() 恢复position到先前标记的mark rewind() position=0,mark=-1.重写读取 flip() limit=position,position=0,mark=-1.准备读取数据 remaining() 返回limit-position,返回还未读取的数据数 clear() limit=capacity,position=0,mark=-1.清空数据(实际上没有,只是会覆盖) compact() 将position到limit的数据前移,position=0,limit=limit-position.清空已读数据 Channel通道
- 通道基于Buffer可以异步读写
FileChannel 文件 注:FIleChannel没有继承SelectableChannel,所以不能设置configureBlocking(false非阻塞).
Path path = Paths.get("~/", "Download"); FileChannel channel = FileChannel.open(path); ByteBuffer buffer = ByteBuffer.allocate(1024); int byteRead = channel.read(buffer); channel.close();
DatagramChannel UDP
DatagramChannel channel = DatagramChannel.open(); ByteBuffer buffer = ByteBuffer.allocate(1024); //接收数据 channel.bind(new InetSocketAddress(1234)); channel.receive(buffer); //发送数据 int send = channel.send(buffer, new InetSocketAddress("localhost", 1234)); channel.close();
SocketChannel TCP
SocketChannel channel = SocketChannel.open(); ByteBuffer buffer = ByteBuffer.allocate(1024); //接收数据 channel.connect(new InetSocketAddress("127.0.0.1", 3333)); channel.read(buffer); //发送数据 channel.write(buffer); channel.close();
ServerSocketChannel 监听TCP,一个请求一个
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress("127.0.0.1", 3333)); ByteBuffer buffer = ByteBuffer.allocate(1024); SocketChannel channel = serverSocketChannel.accept(); //接收数据 channel.read(buffer); //发送数据 channel.write(buffer); serverSocketChannel.close(); channel.close();
AsynchronousFileChannel 异步文件通道 java7增加的异步文件读写(了解一下, 不知道与AIO有什么关系)
//读 AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardpenOption.READ); //用Future接受数据 Future<Integer> future = channel.read(buffer, position); //用CompletionHandler接受数据 channel.read(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>) //写 AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardpenOption.WRITE); //用Future接受数据 Future<Integer> future = channel.write(buffer, position); //用CompletionHandler接受数据 channel.write(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>)
Scatter/Gather
- 本地矢量I/O
- 可以对多个Buffer进行操作
- Scatter: 从一个Channel中读取数据按顺序分散到多个Buffer(就是一个Buffer[])中
- Gather: 将多个Buffer(就是一个Buffer[])中的数据按顺序发送到一个Channel中
- 通道间通讯
- transferFrom(ReadableByteChannel src, long position, long count)从其他到自己
- transferTo(long position, long count, WritableByteChannel target)从自己到目标
Selector选择器
- 亦称多路复用器
- 检查n个Chnnel是否处于可读/可写,从而实现单线程管理多个Channel
使用
ServerSockerChannel sschannel = ServerSocketChannel.open(); ssc.socket().bind(new InetSocketAddress("127.0.0.1", "3333"); //选择器操作 sschannel.configureBlocking(false);//abstract SelectableChannel configureBlocking(boolean block) Selector selector = Selector.open(); sschannel.register(selector, SelectionKey.OP_READ);//这里可以接收一个SelectionKey的返回值 while(true) { Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); keyIterator.remove(); if (key.isAcceptable()) { SockerChannel channel = sschannel.accept(); channel.configureBlocking(false); channel.register(selector, SelectionKey.OP_READ); } else if (key.isConnectable) { //... } else if (key.isReadable) { SocketChannel channel = (SocketChannel)key.channel(); readBuffer.clear(); channel.read(readBuffer); key.interestOps(SelectionKey.OP_WRITE); } else if (key.isWritable) { SocketChannel channel = (SocketChannel)key.channel(); channel.write(writeBuffer); key.interestOps(SelectionKey.OP_READ); } keyIterator.remove(); } }
register()第二个参数是”interest集合”(注意是集合可以不止一个),channel对4种时间感兴趣
- Connect->SelectionKey.OP_CONNECT
- Accept->SelectionKey.OP_ACCEPT
- Read->SelectionKey.OP_READ
- Write->SelectionKey.OP_WRITE
- SelectionKey
- 表示一个特定的Channel与一个特定的Selector之间的注册关系
- 方法
方法 描述 attachment() 返回attachment,attachment可以在注册时指定 channel() 返回对应的channel selector() 返回对应的selector int interestOps() 返回事件,用返回值&Selectionkey.OP_XXX得到一个boolean值 readyOps() 返回已经准备就绪的操作的集合 - 从Selector中选择channel(Selector维护三种SelectionKey集合)
- Registered key set
- Selected key set
- Cancelled key set
- 唤醒阻塞线程的方法
- wakeup(): 使处于阻塞状态的select()理科返回该方法上第一个还没有返回的操作.若没有则下一个select()立刻调用
- close(): 通过关闭Selector是任何一个阻塞线程都被唤醒,同时注册的channel都被注销.zhuxiao