Java NIO 之Channel

偏执的太偏执、 2022-05-22 11:19 413阅读 0赞

定义

  • 用于源节点和目标节点之间的连接。nio中负责缓冲区中数据传输,Channel本地并不存储数据,而是配合缓冲区进行数据传输。你可以把它理解成io中的流。

结构(java.nio.channels.Channel)

  • Channel接口
  • 实现类
  1. * FileChannel
  2. * SocketChannel(用于TCP通讯)
  3. * ServerSocetChannel(用于监听端口)
  4. * DatagramChannel(用于UDP通讯)
  • 最主要的作用还是“非阻塞式读写”

获取Channel的方式

  • java针对支持通道的类提供了getChannel()来获取
    如:FileInputStream/FileOutputStream Socket DatagramSocket等
  • 在jdk1.7以后针对各个通道提供了静态方法open()
  • 在jdk1.7以后的Files工具类的newByteChannel()

通道间的数据传输(例子)

  • 文件复制

    public static void main(String[] args) throws Exception {

    1. FileInputStream in = new FileInputStream("d:\\design.rar");
    2. FileOutputStream out = new FileOutputStream("d:\\test.rar");
    3. FileChannel inChannel = in.getChannel();
    4. FileChannel outChannel = out.getChannel();
    5. ByteBuffer buffer = ByteBuffer.allocate(1024);
    6. while (inChannel.read(buffer) != -1) {
    7. // 切换读写的数据模式
    8. buffer.flip();
    9. outChannel.write(buffer);
    10. // 清空缓冲区
    11. buffer.clear();
    12. }
    13. inChannel.close();
    14. outChannel.close();
    15. in.close();
    16. out.close();
    17. System.out.println("over");
    18. }
  • 直接缓冲区通道完成文件的复制

    public static void test02() throws Exception {

    1. FileChannel inChannel = FileChannel.open(Paths.get("d:\\design.rar"), StandardOpenOption.READ);
    2. FileChannel outChannel = FileChannel.open(Paths.get("D:\\test1.rar"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
    3. // 内存映射文件
    4. MappedByteBuffer inMappedByteBuffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
    5. MappedByteBuffer outMappedByteBuffer = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());
    6. //直接对缓冲区进行数据读写操作
    7. byte[] arr = new byte[inMappedByteBuffer.limit()];
    8. inMappedByteBuffer.get(arr);
    9. outMappedByteBuffer.put(arr);
    10. inChannel.close();
    11. outChannel.close();
    12. System.out.println("over");
    13. }
  • ServerSocketChannel和SocketChannel的使用

    public class WebServer {

    1. public static void main(String[] args) {
    2. test01();
    3. }
    4. public static void test01() {
    5. try {
    6. ServerSocketChannel ssc = ServerSocketChannel.open();
    7. ssc.socket().bind(new InetSocketAddress("127.0.0.1", 8000));
    8. SocketChannel socketChannel = ssc.accept();
    9. ByteBuffer buffer = ByteBuffer.allocate(1024);
    10. socketChannel.read(buffer);
    11. buffer.flip();
    12. while (buffer.hasRemaining()) {
    13. System.out.println((char)buffer.get());
    14. }
    15. socketChannel.close();
    16. ssc.close();
    17. } catch (IOException e) {
    18. e.printStackTrace();
    19. }
    20. }

    }

    public class WerClient {

    1. public static void main(String[] args) {
    2. test01();
    3. }
    4. public static void test01() {
    5. SocketChannel socketChannel = null;
    6. try {
    7. socketChannel = SocketChannel.open();
    8. socketChannel.connect(new InetSocketAddress("127.0.0.1", 8000));
    9. ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
    10. writeBuffer.put("hello world".getBytes());
    11. // 写模式转读模式
    12. writeBuffer.flip();
    13. socketChannel.write(writeBuffer);
    14. socketChannel.close();
    15. } catch (IOException e) {
    16. e.printStackTrace();
    17. }
    18. }

其他

  • 以FIleChannel为例,里面还有很多其他方法,如transferTo()等都可以实现文件复制,大家可以看源代码好好研究下

    public abstract class FileChannel extends AbstractInterruptibleChannel implements SeekableByteChannel, GatheringByteChannel, ScatteringByteChannel {

    1. /** * Initializes a new instance of this class. */
    2. protected FileChannel() { }
    3. public static FileChannel open(Path path,
    4. Set<? extends OpenOption> options,
    5. FileAttribute<?>... attrs)
    6. throws IOException
    7. {
    8. FileSystemProvider provider = path.getFileSystem().provider();
    9. return provider.newFileChannel(path, options, attrs);
    10. }
    11. @SuppressWarnings({

    “unchecked”, “rawtypes”}) // generic array construction

    1. private static final FileAttribute<?>[] NO_ATTRIBUTES = new FileAttribute[0];
  1. public static FileChannel open(Path path, OpenOption... options)
  2. throws IOException
  3. {
  4. Set<OpenOption> set = new HashSet<OpenOption>(options.length);
  5. Collections.addAll(set, options);
  6. return open(path, set, NO_ATTRIBUTES);
  7. }
  8. public abstract int read(ByteBuffer dst) throws IOException;
  9. public abstract long read(ByteBuffer[] dsts, int offset, int length)
  10. throws IOException;
  11. public final long read(ByteBuffer[] dsts) throws IOException {
  12. return read(dsts, 0, dsts.length);
  13. }
  14. public abstract int write(ByteBuffer src) throws IOException;
  15. public abstract long write(ByteBuffer[] srcs, int offset, int length)
  16. throws IOException;
  17. public final long write(ByteBuffer[] srcs) throws IOException {
  18. return write(srcs, 0, srcs.length);
  19. }
  20. public abstract long position() throws IOException;
  21. public abstract long size() throws IOException;
  22. public abstract void force(boolean metaData) throws IOException;
  23. public abstract long transferFrom(ReadableByteChannel src,
  24. long position, long count)
  25. throws IOException;
  26. public abstract int read(ByteBuffer dst, long position) throws IOException;
  27. public abstract int write(ByteBuffer src, long position) throws IOException;
  28. public static class MapMode {
  29. /** * Mode for a read-only mapping. */
  30. public static final MapMode READ_ONLY
  31. = new MapMode("READ_ONLY");
  32. /** * Mode for a read/write mapping. */
  33. public static final MapMode READ_WRITE
  34. = new MapMode("READ_WRITE");
  35. /** * Mode for a private (copy-on-write) mapping. */
  36. public static final MapMode PRIVATE
  37. = new MapMode("PRIVATE");
  38. private final String name;
  39. private MapMode(String name) {
  40. this.name = name;
  41. }
  42. public String toString() {
  43. return name;
  44. }
  45. }
  46. public abstract MappedByteBuffer map(MapMode mode,
  47. long position, long size)
  48. throws IOException;
  49. public abstract FileLock lock(long position, long size, boolean shared)
  50. throws IOException;
  51. public final FileLock lock() throws IOException {
  52. return lock(0L, Long.MAX_VALUE, false);
  53. }
  54. public abstract FileLock tryLock(long position, long size, boolean shared)
  55. throws IOException;
  56. public final FileLock tryLock() throws IOException {
  57. return tryLock(0L, Long.MAX_VALUE, false);
  58. }
  59. }

尽量看源代码,这样理解和记忆都会加深一些。我觉得老外写的英文注释写的很“啰嗦”,如果英文好话,应该可以看得懂意思,再加上代码,也能理解。

发表评论

表情:
评论列表 (有 0 条评论,413人围观)

还没有评论,来说两句吧...

相关阅读

    相关 java nio channel

    Java NIO 通道类似于流,但又有一下不同: 1、既可以从通道中读取数据,也可以写数据到通道中。java .io 中的流是单向性。 2、通道数据读取可以异步。 3、通

    相关 Java NIO Channel

    定义 用于源节点和目标节点之间的连接。nio中负责缓冲区中数据传输,Channel本地并不存储数据,而是配合缓冲区进行数据传输。你可以把它理解成io中的流。 结

    相关 NIOChannel

    1、基本概念 Java NIO中,channel用于数据的传输,类似于传统BIO中的流(IOStream)的概念。 我们都知道,系统的I/O都分为两个阶段: 等