NIO基础篇(三)
NIO里对性能提升最显著的是内存映射(memory mapping),内存访问的速度往往比文件访问的速度快几个数量级。
在内存映射之前,还需要看NIO的一些其他的特性。
缓冲区分片
slice()方法根据现有的缓冲区创建一个子缓冲区。也就是说,它创建一个新的缓冲区,新缓冲区与原来的缓冲区的一部分共享数据。
package nio;
import java.nio.ByteBuffer;
public class SliceTest {
public static void main(String [ ] args) {
ByteBuffer buffer = ByteBuffer.allocate( 10 );
for (int i=0; i<buffer.capacity(); ++i) {
buffer.put( (byte)i );
}
buffer.position( 3 );
buffer.limit( 7 );
ByteBuffer slice = buffer.slice();
System.out.println("slice contains: ");
while (slice.remaining()>0) {
System.out.println(slice.get() );
}
for (int i=0; i<slice.capacity(); ++i) {
byte b = slice.get( i );
b *= 11;
slice.put( i, b );
}
System.out.println("================");
buffer.position( 0 );
buffer.limit( buffer.capacity() );
while (buffer.remaining()>0) {
System.out.println( buffer.get() );
}
}
}
输出结果为:
slice contains:
3
4
5
6
================
0
1
2
33
44
55
66
7
8
9
分散和聚集
一个分散的读取就像一个常规通道读取,只不过它是将数据读到一个缓冲区数组中而不是读到单个缓冲区中。同样地,一个聚集写入是向缓冲区数组而不是向 单个缓冲区写入数据。
你可能在编写一个使用消息对象的网络应用程序,每一个消息被划分为固定长度的头部和固定长度的正文。您可以创建一个刚好可以容纳头部的缓冲区和另一个刚好可以容难正文的缓冲区。当您将它们放入一个数组中并使用分散读取来向它们读入消息时,头部和正文将整齐地划分到这两个缓冲区中。一个缓冲区读完后,剩余的数据会依次读入剩余的缓冲区中。
ByteBuffer header = ByteBuffer.allocate (32);
ByteBuffer body = ByteBuffer (640 * 480);
fileChannel.read (header);
fileChannel.read (body);
大多数NIO通道支持分散/聚集, 上面的可以写成:
ByteBuffer [] scatterBuffers = { header, colorMap, imageBody };
fileChannel.read (scatterBuffers);
ScatteringByteChannel 是一个具有两个附加读方法的通道:
long read( ByteBuffer[] dsts );long read( ByteBuffer[] dsts, int offset, int length );
聚集写入 类似于分散读取,只不过是用来写入。它也有接受缓冲区数组的方法:
long write( ByteBuffer[] srcs );long write( ByteBuffer[] srcs, int offset, int length );
聚集写对于把一组单独的缓冲区中组成单个数据流很有用。为了与上面的消息例子保持一致,您可以使用聚集写入来自动将网络消息的各个部分组装为单个数据流,以便跨越网络传输消息。
字符集
这是一个在处理大文本文件字符编码转换时碰到的问题,即使用CharsetDecoder.decode()方法解码一个MappedByteBuffer对象时,如果这个MBB对象的长度设置的不好,可能会出现“java.nio.charset.MalformedInputException:Malformed
input length is 2.”的错误。但是如果直接使用Charset.decode()方法,则不会出现这样的错误。两端代码片段如下:
File infile = new File(inFilename);
RandomAccessFile raf = new RandomAccessFile(infile, "r");
MappedByteBuffer mbb = raf.getChannel().map(FileChannel.MapMode.READ_ONLY,,);
Charset inCharset = Charset.forName("GBK");
Charset outCharset = Charset.forName("UTF-8"); CharsetDecoder inDecoder = inCharset.newDecoder();
CharsetEncoder outEncoder = outCharset.newEncoder(); CharBuffer cb = inDecoder.decode(mbb); ByteBuffer outbb = outEncoder.encode(cb); CharSequence str = new String(outbb.array());
System.out.println("str is :"+str);
直接使用Charset.decode()方法:
File infile = new File(inFilename);
RandomAccessFile raf = new RandomAccessFile(infile, "r");
MappedByteBuffer mbb = raf.getChannel().map(FileChannel.MapMode.READ_ONLY,0,6000);
Charset inCharset = Charset.forName("GBK");
Charset outCharset = Charset.forName("UTF-8"); //CharsetDecoder inDecoder = inCharset.newDecoder();
//CharsetEncoder outEncoder = outCharset.newEncoder(); CharBuffer cb = inCharset.decode(mbb); ByteBuffer outbb = outCharset.encode(cb); CharSequence str = new String(outbb.array());
System.out.println("str is :"+str);
文件锁定
读文件时将获得一个共享锁,写文件时将获得一个 排它锁。
要获取文件的一部分上的锁,你要调用一个打开的FileChannel上的lock()方法。注意,如果要获取一个排它锁,你必须以写方式打开文件。
RandomAccessFile raf = new RandomAccessFile( "usefilelocks.txt", "rw" );
FileChannel fc = raf.getChannel();
FileLock lock = fc.lock( start, end, false );
操作完成后,需要释放锁,最好放在finally中执行:
lock.release();
正则表达式
正则表达式并不是NIO特有的特性,但是使用正则表达式,使用Pattern和Matcher将可以快速地完成一些查找、替换、校验的工作。
NIO基础篇(三)的更多相关文章
- NIO相关基础篇三
转载请注明原创出处,谢谢! 说在前面 上篇NIO相关基础篇二,主要介绍了文件锁.以及比较关键的Selector,本篇继续NIO相关话题内容,主要谈谈一些Linux 网络 I/O模型.零拷贝等一些内容, ...
- docker+k8s基础篇三
Docker+K8s基础篇(三) kubernetes上的资源 A:k8s上的常用资源 Pod的配置清单 A:Pod上的清单定义 B:Pod创建资源的方法 C:spec下其它字段的介绍 Pod的生命周 ...
- Hybrid APP基础篇(三)->Hybrid APP之Native和H5页面交互原理
本文已经不维护,新地址: http://www.cnblogs.com/dailc/p/8097598.html 说明 Hybrid模式原生和H5交互原理 目录 前言 参考来源 前置技术要求 楔子 A ...
- Python基础篇(三)_函数及代码复用
Python基础篇_函数及代码复用 函数的定义.使用: 函数的定义:通过保留字def实现. 定义形式:def <函数名>(<参数列表>): <函数体> return ...
- JavaScript笔记基础篇(三)
针对前段JS获取当前时间或者对时间数据处理方法汇总: javascript 字符串转化为日期 Java代码 var s="2010-5-18 12:30:20"; var t= ...
- NIO基础篇(二)
Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件.这样,一个单独的线程可以管理多个channel,从而管理多个网络连接. 传统的 ...
- NIO基础篇(一)
1.NIO与传统IO的比较 Java的NIO(New IO)是不同于旧IO的,旧的IO是基于字节流和字符流的,是阻塞的IO.NIO是基于通道(Channel)和缓冲区(Buffer)的,是非阻塞的IO ...
- 前端开发之JavaScript基础篇三
主要内容: 1.创建对象的几种方式 2.JavaScript内置对象 3.JavaScript错误--Throw.Try 和 Catch 4.JavaScript 表单验证 一.创建对象的几种方式 1 ...
- Java面试题-基础篇三(干货)
这些JAVA基础题确定都会了吗? 31.String s = new String("xyz");创建了几个StringObject?是否可以继承String类? 两个或一个都有可 ...
随机推荐
- 我的第二个网页制作:p,hn,br标签的使用
<html> <head> <title>这是我的第二个html代码</title> <body> <!-- <p>Hel ...
- [bzoj4410] [Usaco2016 Feb]Fence in
根据ccz181078大爷的题解可得(QAQ,每次肯定是断掉连续一行||一列的栅栏... 贪心地想,一个格子与外面联通,显然是先把短的边界断掉(就像mst那样 但是比较蛋疼的是,因为我们每次断的时候, ...
- How Many Sets I(容斥定理)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3556 How Many Sets I Time Limit: 2 ...
- JAVA爬虫实践(实践一:知乎)
爬虫顺序 1.分析网站网络请求 通过浏览器F12开发者工具查看网站的内容获取方式. 2.模拟HTTP请求,获取网页内容. 可以采用HttpClient,利用JAVA HttpClient工具可以模拟H ...
- SPRING BOOT跨域访问处理
尊重原创:http://blog.csdn.net/ruiguang21/article/details/77878933 问题场景:由于项目中使用到跨域访问,今天也得到高人指点,所以写出来分享给大家 ...
- 6.移植uboot-支持yaffs烧写,打补丁
在上一章,裁剪uboot以及分区后,本章主要使uboot支持yaffs以及制作补丁 1. 修改uboot支持yaffs 首先,每个命令都会对应一个文件,比如nand命令对应的common/cmd_na ...
- win10安装配置jdk的环境变量
换了个硬盘,用上了win10,发现win10安装好jdk之后,配置环境变量这个相对于win7和xp还是有那么一丢丢区别的,趁着夜色,随笔一记. 1.安装jdk之后,或者也可以用之前安装好的文件夹,先记 ...
- asp.net -mvc框架复习(11)-基于三层架构与MVC实现完整的用户登录
一.先从M部分写起(Modles\DAL\BLL) 1.Modles 实体类:上次实体类已经搞定. 2.DAL 数据访问类类 (1)通用数据数据访问类: A: 先编写数据连接字符串,写到网站根目录W ...
- JavaScript的三种类型检测typeof , instanceof , toString比较
1.typeof typeof是js的一个操作符,在类型检测中,几乎没有任何用处. typeof 返回一个表达式的数据类型的字符串,返回结果为javascript中的基本数据类型,包括:number. ...
- 新建maven项目,JRE System Library[J2SE-1.5]
上篇博文中搭建了maven多模块项目,发现全是JRE System Library[J2SE-1.5],如图. 怎么避免这种情况呢? windows-preferences-maven-user se ...