栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Netty 入门篇 Day 2---ByteBuffer

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Netty 入门篇 Day 2---ByteBuffer

3.ByteBuffer的使用

文章目录
    • 3.ByteBuffer的使用
      • 3.1ByteBuffer的使用步骤
      • 3.2ByteBuffer的内存结构
      • 3.3ByteBuffer的常见方法
      • 3.4字符串和ByteBuffer的转换
      • 3.5综合练习
    • 4.FileChannel的使用
    • 5.其它相关的类
  • 结语

3.1ByteBuffer的使用步骤
1> 往buffer中写数据,可以通过 channel.read(buffer)
2> 切换buffer为 读模式, 通过 buffer.flip()
3> 从buffer中读取数据, 调用buffer.get()
4> 切换buffer为 写模式, 通过 buffer.clear() 或 buffer.compact()
重复1-4步
3.2ByteBuffer的内存结构
ByteBuffer的主要属性:
     capacity   容量/总大小
     position   读或写时指针的位置索引下标
     limit      限制(限制读或写允许的最大大小)
创建ByteBuffer对象:
     ByteBuffer buffer = ByteBuffer.allocate(10);

初始状态(写模式):

缓冲区内存分配后,默认处于写模式,positon为0, capacity和limit相同 均为最大容量10。

3.3ByteBuffer的常见方法
1. 分配空间
    ByteBuffer.allocate(长度);  // 分配堆空间
2. 向缓冲区中写数据
    buffer.put((byte)'a');
    buffer.put(new byte[]{(byte)'c', (byte)'d'});
    或
    int len = channel.read(buffer);
3. 从buffer中读内容
    byte b = buffer.get(); // 读1个字节内容,并返回    position会变
    byte b = buffer.get(idx); // 读指定索引处的1个字节内容,并返回     position不会变
    或
    channel.write(buffer);
    
    注意:读模式下 可以使用 buffer.rewind(); 重置position的值为0,相当于重头开始读。
4. mark和reset
	buffer.mark();  在当前position做标记
	buffer.reset();  回到标记位置
	注意:rewind和flip都会清除mark的位置内容。
3.4字符串和ByteBuffer的转换
ByteBuffer buffer1 = ByteBuffer.allocate(16);

// String -> buffer
// 1. put
buffer1.put("hello".getBytes());
ByteBufferUtil.debugAll(buffer1); // position: [5], limit: [16]

// 2. Charset
// 写完后 直接切换到读模式
ByteBuffer buffer2 = StandardCharsets.UTF_8.encode("你好");
ByteBufferUtil.debugAll(buffer2); // position: [0], limit: [6]

// 3. wrap
// 写完后 直接切换到读模式
ByteBuffer buffer3 = ByteBuffer.wrap("hello".getBytes());
ByteBufferUtil.debugAll(buffer3); // position: [0], limit: [5]

// buffer -> String
// 使用第2 和 3种方式,直接读即可
String str = StandardCharsets.UTF_8.decode(buffer2).toString();
System.out.println(str); // 你好

// 第1种写的方式 ,必须 先切换到读模式 才能读取
buffer1.flip();  // position: [0], limit: [5]
String str2 = StandardCharsets.UTF_8.decode(buffer1).toString();
System.out.println(str2); // hello
3.5综合练习
	public static void main(String[] args) {
        ByteBuffer buffer = ByteBuffer.allocate(40);
        buffer.put("Hello World!nI'm Baizhi!nHo".getBytes());
        split(buffer);
        buffer.put("w are you?n".getBytes());
        split(buffer);
    }
    // 拆分缓冲区中的数据
    private static void split(ByteBuffer source){
        source.flip(); // 切换原缓冲区为 读模式

        // 依次按字节读取原缓冲区内容,当读到n, 把完整的1项内容  写到新缓冲区
        // 依次按字节读取原缓冲区内容
        for(int i=0; i
            // 当读到 n 时  (格式正确 的一项完整内容)
            if (source.get(i)=='n'){
                // 把格式正确的数据 存入 新的缓冲区
                // 获取实际读到的字节数量
                int length = i - source.position() + 1;
                // System.out.println(i);
                // 分配新缓冲区内存大小 (实际读到的字节数量)
                ByteBuffer target = ByteBuffer.allocate(length);
                // 从source中读, 边读 边写入target
                for(int j=0; j
                    target.put(source.get()); // 使用get()读内容时,position会发生改变
                }
                ByteBufferUtil.debugAll(target);
            }
            // System.out.println((char)source.get(i));
        }

        // 切换原缓冲区为 写模式
        // 注意:此外必须为compact,把未读的内容 自动前移(相当于删除了已读过的内容),且position为未读内容的长度
        //   未读的内容  将和 新内容 连接到一起
        source.compact();
    }
4.FileChannel的使用
对文件进行操作处理的channel
1> 获取FileChannel
	通过FileInputStream、FileOutputStream或者RandomAccessFile对象 的getChannel()方法 来进行获取。
	a) 通过FileInputStream获取的channe 只能读
	b) 通过FileOutputStream获取的channe 只能写
	c) 通过RandomAccessFile的不同构造,可以设置channel为可读或可写模式
2> 读取
	// 通过channel读数据 并保存到buffer缓冲区
	int len = channel.read(buffer);// 返回裤子坟场到的字节数,-1代表读到了结尾
3> 写入
    // 把buffer缓冲区中的内容 通过channel写到文件
	channel.write(buffer);
4> 关闭
	if (channel!=null) channel.close();
5> 位置
	long pos = channel.position();  // 获取channel的当前位置
	channel.position(pos); // 设置channel的位置
6> 大小
	channel.size(); // 获取文件的大小

案例:简单的文件拷贝(2G以内的文件)

 // 文件的拷贝(缺点: 适用于文件大小2G以内)
public static void main(String[] args) {
    FileChannel readChannel = null;
    FileChannel toChannel = null;
    try{
        readChannel = new FileInputStream("e:\data.txt").getChannel(); // 创建读文件的channel
        toChannel = new FileOutputStream("e:\to.txt").getChannel(); // 创建写文件的channel

        readChannel.transferTo(0, readChannel.size(), toChannel); // 文件传输/拷贝

        System.out.println("file copy ok...");
    } catch(Exception e) {
        e.printStackTrace();
    } finally {
        // 关闭channel
        try {
            if (readChannel != null) readChannel.close();
            if (toChannel != null) toChannel.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
5.其它相关的类
JDK7+ 引入了Path、Paths、Files 类
1> Path: 表示文件路径
2> Paths:是工具类,用于获取Path实例
	如:Path path = Paths.get("e:\data.txt"); // 获取到了一个Path对象
3> Files: 工具类,提供对文件进行操作的工具方法
	如:Path path = Paths.get("e:\data.txt");
	   boolean bn = Files.exists(path);  // 判断文件是否存在
       Files.createDirectory(path); // 创建目录
       
       Path path1 = Paths.get("e:\data.txt"); 
       Path path2 = Paths.get("e:\to.txt"); 
       Files.copy(path1, path2);
       ...

; // 判断文件是否存在
Files.createDirectory(path); // 创建目录

   Path path1 = Paths.get("e:\data.txt"); 
   Path path2 = Paths.get("e:\to.txt"); 
   Files.copy(path1, path2);
   ...
结语

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、评论、收藏➕关注,您的支持是我坚持写作最大的动力。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1027475.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号