Java NIO 之Channel
定义
- 用于源节点和目标节点之间的连接。nio中负责缓冲区中数据传输,Channel本地并不存储数据,而是配合缓冲区进行数据传输。你可以把它理解成io中的流。
结构(java.nio.channels.Channel)
- Channel接口
- 实现类
* FileChannel
* SocketChannel(用于TCP通讯)
* ServerSocetChannel(用于监听端口)
* DatagramChannel(用于UDP通讯)
- 最主要的作用还是“非阻塞式读写”
获取Channel的方式
- java针对支持通道的类提供了getChannel()来获取
如:FileInputStream/FileOutputStream Socket DatagramSocket等 - 在jdk1.7以后针对各个通道提供了静态方法open()
- 在jdk1.7以后的Files工具类的newByteChannel()
通道间的数据传输(例子)
文件复制
public static void main(String[] args) throws Exception {
FileInputStream in = new FileInputStream("d:\\design.rar");
FileOutputStream out = new FileOutputStream("d:\\test.rar");
FileChannel inChannel = in.getChannel();
FileChannel outChannel = out.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (inChannel.read(buffer) != -1) {
// 切换读写的数据模式
buffer.flip();
outChannel.write(buffer);
// 清空缓冲区
buffer.clear();
}
inChannel.close();
outChannel.close();
in.close();
out.close();
System.out.println("over");
}
直接缓冲区通道完成文件的复制
public static void test02() throws Exception {
FileChannel inChannel = FileChannel.open(Paths.get("d:\\design.rar"), StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("D:\\test1.rar"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
// 内存映射文件
MappedByteBuffer inMappedByteBuffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer outMappedByteBuffer = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());
//直接对缓冲区进行数据读写操作
byte[] arr = new byte[inMappedByteBuffer.limit()];
inMappedByteBuffer.get(arr);
outMappedByteBuffer.put(arr);
inChannel.close();
outChannel.close();
System.out.println("over");
}
ServerSocketChannel和SocketChannel的使用
public class WebServer {
public static void main(String[] args) {
test01();
}
public static void test01() {
try {
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress("127.0.0.1", 8000));
SocketChannel socketChannel = ssc.accept();
ByteBuffer buffer = ByteBuffer.allocate(1024);
socketChannel.read(buffer);
buffer.flip();
while (buffer.hasRemaining()) {
System.out.println((char)buffer.get());
}
socketChannel.close();
ssc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class WerClient {
public static void main(String[] args) {
test01();
}
public static void test01() {
SocketChannel socketChannel = null;
try {
socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("127.0.0.1", 8000));
ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
writeBuffer.put("hello world".getBytes());
// 写模式转读模式
writeBuffer.flip();
socketChannel.write(writeBuffer);
socketChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
其他
以FIleChannel为例,里面还有很多其他方法,如transferTo()等都可以实现文件复制,大家可以看源代码好好研究下
public abstract class FileChannel extends AbstractInterruptibleChannel implements SeekableByteChannel, GatheringByteChannel, ScatteringByteChannel {
/** * Initializes a new instance of this class. */
protected FileChannel() { }
public static FileChannel open(Path path,
Set<? extends OpenOption> options,
FileAttribute<?>... attrs)
throws IOException
{
FileSystemProvider provider = path.getFileSystem().provider();
return provider.newFileChannel(path, options, attrs);
}
@SuppressWarnings({
“unchecked”, “rawtypes”}) // generic array construction
private static final FileAttribute<?>[] NO_ATTRIBUTES = new FileAttribute[0];
public static FileChannel open(Path path, OpenOption... options)
throws IOException
{
Set<OpenOption> set = new HashSet<OpenOption>(options.length);
Collections.addAll(set, options);
return open(path, set, NO_ATTRIBUTES);
}
public abstract int read(ByteBuffer dst) throws IOException;
public abstract long read(ByteBuffer[] dsts, int offset, int length)
throws IOException;
public final long read(ByteBuffer[] dsts) throws IOException {
return read(dsts, 0, dsts.length);
}
public abstract int write(ByteBuffer src) throws IOException;
public abstract long write(ByteBuffer[] srcs, int offset, int length)
throws IOException;
public final long write(ByteBuffer[] srcs) throws IOException {
return write(srcs, 0, srcs.length);
}
public abstract long position() throws IOException;
public abstract long size() throws IOException;
public abstract void force(boolean metaData) throws IOException;
public abstract long transferFrom(ReadableByteChannel src,
long position, long count)
throws IOException;
public abstract int read(ByteBuffer dst, long position) throws IOException;
public abstract int write(ByteBuffer src, long position) throws IOException;
public static class MapMode {
/** * Mode for a read-only mapping. */
public static final MapMode READ_ONLY
= new MapMode("READ_ONLY");
/** * Mode for a read/write mapping. */
public static final MapMode READ_WRITE
= new MapMode("READ_WRITE");
/** * Mode for a private (copy-on-write) mapping. */
public static final MapMode PRIVATE
= new MapMode("PRIVATE");
private final String name;
private MapMode(String name) {
this.name = name;
}
public String toString() {
return name;
}
}
public abstract MappedByteBuffer map(MapMode mode,
long position, long size)
throws IOException;
public abstract FileLock lock(long position, long size, boolean shared)
throws IOException;
public final FileLock lock() throws IOException {
return lock(0L, Long.MAX_VALUE, false);
}
public abstract FileLock tryLock(long position, long size, boolean shared)
throws IOException;
public final FileLock tryLock() throws IOException {
return tryLock(0L, Long.MAX_VALUE, false);
}
}
尽量看源代码,这样理解和记忆都会加深一些。我觉得老外写的英文注释写的很“啰嗦”,如果英文好话,应该可以看得懂意思,再加上代码,也能理解。
还没有评论,来说两句吧...