1.Buffer类图
新创建的ByteBuffer,四个属性的位置
capacity:容量,指定缓冲区的大小。
ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);
limit:第一个不应该读取或写入的元素的索引。缓冲区的限制不能为负,并且不能大于其容量。
Position: 下一个要读取或写入的元素的索引。缓冲区的位置不能为负,并且不能大于其限制。
遵循条件:0 <= 标记 <= 位置 <=
限制 <= 容量
不同的方法都是编辑buffer,移动这些标记。有四个方法需要重点关注
Buffer.clear();
Buffer.compact();
Buffer.flip();
Buffer.rewind();
clear();
compact(); The compact method moves the elements between the current position and the limit to the begging of the buffer.
flip(); The flip method need to be called before reading the data from the buffer.
rewind();
Direct vs. nonDirect buffers:
字节缓冲区要么是直接的,要么是非直接的。如果为直接字节缓冲区,则 Java 虚拟机会尽最大努力直接在此缓冲区上执行本机 I/O
操作。也就是说,在每次调用基础操作系统的一个本机 I/O 操作之前(或之后),虚拟机都会尽量避免将缓冲区的内容复制到中间缓冲区中(或从中间缓冲区中复制内容)。
直接字节缓冲区可以通过调用此类的 allocateDirect
工厂方法来创建。此方法返回的缓冲区进行分配和取消分配所需成本通常高于非直接缓冲区。
NonDirect: if you create a buffer that will not interact with native resource (ex. Just to store a String) you should use a NonDirect Buffer.
Adding to a Buffer: When adding data to a buffer you can use the wrap() method. Note that when a buffer is created by wrapping it are never direct.
/* * wraps a string inside an buffer.
*/
String string = "Text to be added";
CharBuffer charBuffer = CharBuffer.allocate(string.length());
charBuffer.wrap(string);
or you could wrap entire blocks of data in a form of an array:
/* * takes a byte array and wraps it into a buffer.
*/
byte[] data = “Text to be added”.getBytes(“UTF-8”);
ByteBuffer buffer1 = ByteBuffer.wrap(data);
Draining a Buffer: Buffers can be drained into any data type:
/* * uses the get() method to fill a string.
*/
String fromBuffer = “”;
while (buffer.hasRemaining()) {
fromBuffer += buffer.get();
}
Data Conversion: Data Conversion is an important aspect of buffers. You can use the factory methods to change a buffer from one type of another:
ByteBuffer byteBuffer = ByteBuffer.allocate(5);
IntBuffer intBuffer = byteBuffer.asIntBuffer();
flip方法:首先将限制设置为当前位置,然后将位置设置为 0。
2.Channel
通道只能在字节缓冲区上操作。
I/O可以分为广义的两大类别:File I/O和Stream I/O。相应地有两种类型的通道文件(file)通道和套接字(socket)通道。FileChannel类和三个socket通道类:SocketChannel、ServerSocketChannel和DatagramChannel。
通道可以以多种方式创建。Socket通道有可以直接创建新socket通道的工厂方法。但是一个FileChannel对象却只能通过在一个打开的RandomAccessFile、FileInputStream或FileOutputStream对象上调用getChannel( )方法来获取。您不能直接创建一个FileChannel对象。
- FileChannel对象是线程安全(thread-safe)的。多个进程可以在同一个实例上并发调用方法而不会引起任何问题,不过并非所有的操作都是多线程的(multithreaded)。影响通道位置或者影响文件大小的操作都是单线程的(single-threaded)。文件锁定模型,锁的对象是文件而不是通道或线程,这意味着文件锁不适用于判优同一台Java虚拟机上的多个线程发起的访问。锁与文件关联,而不是与通道关联。我们使用锁来判优外部进程,而不是判优同一个Java虚拟机上的线程。
- Socket Channel。请注意DatagramChannel和SocketChannel实现定义读和写功能的接口而ServerSocketChannel不实现。ServerSocketChannel负责监听传入的连接和创建新的SocketChannel对象,它本身从不传输数据。
为了加深理解,自己写了一个小示例代码实现本地文件拷贝,类似上传:
package com.zhang.nio;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* 使用NIO上传文件
* <p />
*
* @author Administrator
*/
public class UploadFile {
private final static int DEFAULT_CAPACITY = 8092;
private final static String SOURCE_FILE_PATH = "F:\\开发工具\\spring-framework-3.0.5.RELEASE-with-docs.zip";
private final static String DEST_PATH = "F:\\test\\test.zip";
/**
* @param args
*/
public static void main(String[] args) {
ByteBuffer buffer = ByteBuffer.allocateDirect(DEFAULT_CAPACITY);
FileInputStream inputStream = null;
FileOutputStream outputStream = null;
FileChannel inChannel = null;
FileChannel outChannel = null;
try {
inputStream = new FileInputStream(SOURCE_FILE_PATH);
outputStream = new FileOutputStream(DEST_PATH);
inChannel = inputStream.getChannel();
outChannel = outputStream.getChannel();
while (inChannel.read(buffer) != -1) {
buffer.flip();
outChannel.write(buffer);
buffer.clear();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
if (inChannel != null) {
inChannel.close();
}
if (outChannel != null) {
outChannel.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
- 大小: 36.8 KB
- 大小: 8.5 KB
- 大小: 96.1 KB
分享到:
相关推荐
### NIO:Channel、Buffer与Selector详解 #### 一、NIO概述 NIO(Non-blocking I/O,非阻塞I/O)是Java为了解决传统阻塞式I/O效率低下的问题而引入的一种新的I/O操作模式。NIO通过引入Channel、Buffer以及Selector...
Next, you'll learn about NIO's buffer, channel, selector, regular expression, charset, and formatter APIs. Finally, you'll discover NIO.2's offerings in terms of an improved file system interface, ...
4. **缓冲区联合使用Channel**:在NIO中,Channel用于读写数据,它可以从源读取数据到Buffer,也可以将Buffer中的数据写入目的地。例如,FileChannel用于文件操作,SocketChannel用于网络通信。 5. **选择器...
尚硅谷_NIO_缓冲区(Buffer)的数据存取 ·03. 尚硅谷_NIO_直接缓冲区与非直接缓冲区 ·04. 尚硅谷_NIO_通道(Channel)的原理与获取 ·05. 尚硅谷_NIO_通道的数据传输与内存映射文件 ·06. 尚硅谷_NIO_分散读取与聚集...
05-Java NIO-Channel-FileChannel详解(一).mp4 06-Java NIO-Channel-FileChannel详解(二).mp4 08-Java NIO-Channel-ServerSocketChannel.mp4 09-Java NIO-Channel-SocketChannel.mp4 10-Java NIO-Channel-...
- **概念**:`java.nio.buffer`包提供了缓冲区的抽象,用于在应用程序和I/O设备之间传输数据。 - **类型**:主要分为两种类型:`DirectByteBuffer` 和 `HeapByteBuffer`。 - **HeapByteBuffer**:在JVM堆上分配空间...
NIO的核心组件包括Buffer(缓冲区)和Channel(通道),它们共同解决了传统I/O模型中的一些性能瓶颈。 1. **Buffer(缓冲区)**: - 缓冲区是NIO中的核心概念,它是一个对象,包含了存储数据的内存块。Buffer有...
Java NIO 中的 Channel(通道)是连接到实体如硬件设备、文件、网络套接字等的开放连接,它能够执行多种 I/O 操作,如读取和写入。相较于传统的 Stream,Channel 提供了一些显著的优势,比如支持异步操作和双向数据...
Java NIO系列教程(二) Channel Java NIO系列教程(三) Buffer Java NIO系列教程(四) Scatter/Gather Java NIO系列教程(五) 通道之间的数据传输 Java NIO系列教程(六) Selector Java NIO系列教程(七) ...
NIO中新增了Buffer(缓冲区)、Channel(通道)和Selector(选择器)的概念。Buffer是一个容器对象,它包含数据,并提供了一组方法来访问这些数据。Channel代表了和文件或其他I/O资源的连接,它是双向的,可以进行...
NIO 的核心组件包括 Channel(通道)、Buffer(缓冲区)和 Selector(选择器)。 - **Channel(通道)**:通道类似于流,但是数据只能从 Channel 读取到 Buffer 中,或者从 Buffer 写入到 Channel 中。 - **Buffer...
Java NIO库提供了多种实现,如`java.nio.channels`包下的各种Channel和Selector类,以及`java.nio`包下的Buffer类。 在学习NIO时,首先需要理解Channel、Buffer、Selector的基本概念和使用方法,然后通过实例来熟悉...
3. **内存直接访问(Direct Buffer)**:NIO支持直接在操作系统内存中创建缓冲区,减少了数据复制带来的开销。 在实现客户端与服务器通信时,Java IO通常通过Socket类进行。客户端创建Socket实例连接到服务器,...
- **线程安全**:NIO操作通常是线程不安全的,所以在多线程环境下,需要对共享的Buffer和Channel进行适当的同步控制。 - **内存管理**:Buffer的容量应合理设置,避免频繁扩容或浪费内存。 - **异常处理**:正确处理...