- 浏览: 115777 次
- 性别:
- 来自: 上海
最新评论
-
ty709928686:
...
导出db2数据库的表结构和数据 -
suifengJC614:
对于你的第一种解决方案,其实不用那么麻烦,如果对外观有要求的话 ...
jcomboBox显示长项目的内容
JDK 1.4的java.nio.*包中引入了新的JavaI/O类库,其目的在于提高速度。(实际上,旧的I/O包已经使用nio重新实现过,以便充分利用这种速度,即使我们不显式地用nio编写代码,也能从中受益!
nio速度的提高来自于所使用的结构更接近于操作系统执行I/O的方式(Java执行I/O接近于操作系统执行I/O,所以速度得到了提高):通道和缓冲器。我们可以把它想象成一个煤矿,通道是一个包含煤层(数据)的矿藏,而缓冲器则是派送到矿藏的卡车。卡车载满煤炭而归,我们再从卡车上获得煤炭。也就是说,我们要读书到数据,并没有直接和通道交互;只是和缓冲器交互,并把缓冲器派送到通道。通道要么从缓冲器获得数据,要么向缓冲器发送数据!
唯一直接与通道交互的缓冲器是ByteBuffer,它是java.nio里面的类:通过告知分配多少存储空间来创建一个ByteBuffer对象,并且还有一个方法选择集,用以原始的字节形式或基本数据类型输出和读取数据。但是没办法输出或读取对象,即使是字符串对象也不行;
ByteBuffer是一个抽象类,不能直接创建实例,可以调用该类的static方法allocate(int capacity)来创建它的一个新缓冲区,该缓冲区的位置将为零,其界限将为其容量,其标记是不确定的。它将具有一个底层实现数组,且其 数组偏移量将为零。
关于通道,这里介绍一个文件通道FileChannel,它也是一个抽象类,也不能直接创建实例。旧的I/O类库中有本个类被修改过了,可以用它们的getChannel()来返回一个FileChannel对象(更确切的说应该是返回FileChannel的一个匿名子类的对象)。这三个能返回FileChannel的类是:FileInputStream,FileOutputStream,RandomAccessFile 。值得注意的是它们都是字节流的,Reader与Writer这两个处理字符流的类不能用于通道,不过java,nio.channels.Channels类提供了实用方法,用以在通道中产生Reader与Writer(想了解更多请查API文档,这里不介绍)!
===========================================================================================
缓冲区是特定基本类型元素的线性有限序列。除内容外,缓冲区的基本属性还包括容量、限制和位置:
缓冲区的容量 是它所包含的元素的数量。缓冲区的容量不能为负并且不能更改。
缓冲区的限制 是第一个不应该读取或写入的元素的索引。缓冲区的限制不能为负,并且不能大于其容量。
缓冲区的位置 是下一个要读取或写入的元素的索引。缓冲区的位置不能为负,并且不能大于其限制。
因此,我们从缓冲区读书数据,其实是从此缓冲区的“位置”处一直读到“限制”处!
============================================================================================
关于缓冲器ByteBuffer,最令人捉摸不清的可能是它的三个方法:flip();clear();remind()
这三个方法一般是和FileChannel的read(ByteBuffer bf)与write(ByteBuffer bf)混合在一起使用的!
FileChannel的read(ByteBuffer bf):将字节序列从FileChannel读入给定的缓冲区ByteBuffer bf 中!读完以后,bf的当前位置就是从FileChannel中读取的字节个数!
同理,我们应该可以很容易想象出write(ByteBuffer bf)它就是用来将字节序列从给定的缓冲区ByteBuffer bf写入通道FileChannel。
ByteBuffer的flip():反转此缓冲区,将限制设置为当前位置,然后将位置设置为 0 !
ByteBuffer的clear();“清除”此缓冲区,将位置设置为 0,将限制设置为容量!此方法不能实际清除缓冲区中的数据,但从名称来看它似乎能够这样做,这样命名是因为它多数情况下确实是在清除数据时使用。因为调用该方法后,我们一般都会调用FileChannel.read(buff)或者buff.put()来把新的数据放到buff中,此时原来的内容就会被新的内容所覆盖!也不是全部覆盖,而是覆盖掉新数据所包含的字节数!所以看起来好象就是原来的内容被删除一样!
remind(),重绕此缓冲区,将位置设置为 0 并丢弃标记。此方法与flip()的区别是:remind()不会把限制设置为当前位置,而是保持限制不变!与clear()的区别是:remind()不会把限制设置为容量,而是保持限制不变!
==========================================================================================
讲了这么多,你们不晕,我都晕了,那么现在来点实际的代码,以帮助理解!
//例一:
import java.nio.channels.*;
import java.io.*;
public class GetChannel {
private static final int BSIZE = 1024;
public static void main(String[] args) throws Exception {
// Write a file:
FileChannel fc =
new FileOutputStream("data.txt").getChannel();
fc.write(ByteBuffer.wrap("Some text ".getBytes()));
fc.close();
// Add to the end of the file:
fc =
new RandomAccessFile("data.txt", "rw").getChannel();
fc.position(fc.size()); // 将通道位置移动到最后,以便我们在通道后面继续写入新数据
fc.write(ByteBuffer.wrap("Some more".getBytes()));
fc.close();
// Read the file:
fc = new FileInputStream("data.txt").getChannel();
ByteBuffer buff = ByteBuffer.allocate(BSIZE);
fc.read(buff); //把通道中的字节序列读入buff中
//进行此操作后,buff的位置移动了从FileChannel中读取的字节个数!
buff.flip(); //为下面的buff.get()做准备,将buff的限制设置为当前位置,然后将位置设置为 0
//因为我们从buff读取,是从此buff的位置处一直读到限制处!
while(buff.hasRemaining())
System.out.print((char)buff.get());
}
} /* Output:
Some text Some more
*///:~
=========================================================================================
//例二:
// Copying a file using channels and buffers
// {Args: ChannelCopy.java test.txt}
import java.nio.*;
import java.nio.channels.*;
import java.io.*;
public class ChannelCopy {
private static final int BSIZE = 1024;
public static void main(String[] args) throws Exception {
if(args.length != 2) {
System.out.println("arguments: sourcefile destfile");
System.exit(1);
}
FileChannel
in = new FileInputStream(args[0]).getChannel(),
out = new FileOutputStream(args[1]).getChannel();
ByteBuffer buffer = ByteBuffer.allocate(BSIZE);
while(in.read(buffer) != -1) { //buffer 用来向FileChannel读取数据
//其实此循环只会执行一次,因为执行一次就会把FileChannel中的全部数据都读到buffer中
buffer.flip(); // 为通道写入做准备
out.write(buffer); //buffer 用来向FileChannel写入数据
buffer.clear(); // 为通道再次读取做准备
}
}
} ///:~
============================启示================================
当对flip(),clear(),remind()不是很理解而正在考虑某个地方是否需要这三个方法时,我们还可以调用limit(),position(),remainning()等方法来进行调试。
public final int limit()
返回此缓冲区的限制。
public final int position()
返回此缓冲区的当前位置。
public final int remaining()
返回当前位置与限制之间的元素数。
======================================================================
上面的两个例子,是因为有FileChannel的read()或者write(),以至把ByteBuffer中的位置移动了相应的字节数。然后调用flip时,就把限制设置为当前位置。此时的position就不为0了。下面的例子中,没有FileChannel的参与,当前位置也就没有了变化,此时,若再调用flip,由于当前位置是0,设置为限制后,限制也变成0,若我们要从限制为0的ByteBuffer中读取数据,此时就什么也没读到,可能还会抛出异常。那么解决的方法就是调用rewind(),此方法,只是把位置设置为0,而不会改变其限制,这时,限制就仍为容量。因为用ByteBuffer的static allocated()时,新缓冲区的位置将为零,其限制将为其容量!
另外,调用ByteBuffer的get()与put()时,会把position移动一个字节!而调用这两个方法的带参数版本则不会改变position的值,这里还要区别一下两种情况的put方法:
情况一:
ByteBuffer bb = ByteBuffer.allocate(1024);
CharBuffer cb = bb.asCharBuffer(); //创建ByteBuffer的Char视图
cb.put("Hwdy!"); ////字符串中的每个字符占1个字节!共占5个字节!所以此句会使position移动5个字节!
===================================================================
情况二:
ByteBuffer bb = ByteBuffer.allocate(BSIZE);
bb.asCharBuffer().put("Howdy"); //用这种形式来创建视图不会移动bb的position
print(bb.position()); //所以此处的postion值为0
nio速度的提高来自于所使用的结构更接近于操作系统执行I/O的方式(Java执行I/O接近于操作系统执行I/O,所以速度得到了提高):通道和缓冲器。我们可以把它想象成一个煤矿,通道是一个包含煤层(数据)的矿藏,而缓冲器则是派送到矿藏的卡车。卡车载满煤炭而归,我们再从卡车上获得煤炭。也就是说,我们要读书到数据,并没有直接和通道交互;只是和缓冲器交互,并把缓冲器派送到通道。通道要么从缓冲器获得数据,要么向缓冲器发送数据!
唯一直接与通道交互的缓冲器是ByteBuffer,它是java.nio里面的类:通过告知分配多少存储空间来创建一个ByteBuffer对象,并且还有一个方法选择集,用以原始的字节形式或基本数据类型输出和读取数据。但是没办法输出或读取对象,即使是字符串对象也不行;
ByteBuffer是一个抽象类,不能直接创建实例,可以调用该类的static方法allocate(int capacity)来创建它的一个新缓冲区,该缓冲区的位置将为零,其界限将为其容量,其标记是不确定的。它将具有一个底层实现数组,且其 数组偏移量将为零。
关于通道,这里介绍一个文件通道FileChannel,它也是一个抽象类,也不能直接创建实例。旧的I/O类库中有本个类被修改过了,可以用它们的getChannel()来返回一个FileChannel对象(更确切的说应该是返回FileChannel的一个匿名子类的对象)。这三个能返回FileChannel的类是:FileInputStream,FileOutputStream,RandomAccessFile 。值得注意的是它们都是字节流的,Reader与Writer这两个处理字符流的类不能用于通道,不过java,nio.channels.Channels类提供了实用方法,用以在通道中产生Reader与Writer(想了解更多请查API文档,这里不介绍)!
===========================================================================================
缓冲区是特定基本类型元素的线性有限序列。除内容外,缓冲区的基本属性还包括容量、限制和位置:
缓冲区的容量 是它所包含的元素的数量。缓冲区的容量不能为负并且不能更改。
缓冲区的限制 是第一个不应该读取或写入的元素的索引。缓冲区的限制不能为负,并且不能大于其容量。
缓冲区的位置 是下一个要读取或写入的元素的索引。缓冲区的位置不能为负,并且不能大于其限制。
因此,我们从缓冲区读书数据,其实是从此缓冲区的“位置”处一直读到“限制”处!
============================================================================================
关于缓冲器ByteBuffer,最令人捉摸不清的可能是它的三个方法:flip();clear();remind()
这三个方法一般是和FileChannel的read(ByteBuffer bf)与write(ByteBuffer bf)混合在一起使用的!
FileChannel的read(ByteBuffer bf):将字节序列从FileChannel读入给定的缓冲区ByteBuffer bf 中!读完以后,bf的当前位置就是从FileChannel中读取的字节个数!
同理,我们应该可以很容易想象出write(ByteBuffer bf)它就是用来将字节序列从给定的缓冲区ByteBuffer bf写入通道FileChannel。
ByteBuffer的flip():反转此缓冲区,将限制设置为当前位置,然后将位置设置为 0 !
ByteBuffer的clear();“清除”此缓冲区,将位置设置为 0,将限制设置为容量!此方法不能实际清除缓冲区中的数据,但从名称来看它似乎能够这样做,这样命名是因为它多数情况下确实是在清除数据时使用。因为调用该方法后,我们一般都会调用FileChannel.read(buff)或者buff.put()来把新的数据放到buff中,此时原来的内容就会被新的内容所覆盖!也不是全部覆盖,而是覆盖掉新数据所包含的字节数!所以看起来好象就是原来的内容被删除一样!
remind(),重绕此缓冲区,将位置设置为 0 并丢弃标记。此方法与flip()的区别是:remind()不会把限制设置为当前位置,而是保持限制不变!与clear()的区别是:remind()不会把限制设置为容量,而是保持限制不变!
==========================================================================================
讲了这么多,你们不晕,我都晕了,那么现在来点实际的代码,以帮助理解!
//例一:
import java.nio.channels.*;
import java.io.*;
public class GetChannel {
private static final int BSIZE = 1024;
public static void main(String[] args) throws Exception {
// Write a file:
FileChannel fc =
new FileOutputStream("data.txt").getChannel();
fc.write(ByteBuffer.wrap("Some text ".getBytes()));
fc.close();
// Add to the end of the file:
fc =
new RandomAccessFile("data.txt", "rw").getChannel();
fc.position(fc.size()); // 将通道位置移动到最后,以便我们在通道后面继续写入新数据
fc.write(ByteBuffer.wrap("Some more".getBytes()));
fc.close();
// Read the file:
fc = new FileInputStream("data.txt").getChannel();
ByteBuffer buff = ByteBuffer.allocate(BSIZE);
fc.read(buff); //把通道中的字节序列读入buff中
//进行此操作后,buff的位置移动了从FileChannel中读取的字节个数!
buff.flip(); //为下面的buff.get()做准备,将buff的限制设置为当前位置,然后将位置设置为 0
//因为我们从buff读取,是从此buff的位置处一直读到限制处!
while(buff.hasRemaining())
System.out.print((char)buff.get());
}
} /* Output:
Some text Some more
*///:~
=========================================================================================
//例二:
// Copying a file using channels and buffers
// {Args: ChannelCopy.java test.txt}
import java.nio.*;
import java.nio.channels.*;
import java.io.*;
public class ChannelCopy {
private static final int BSIZE = 1024;
public static void main(String[] args) throws Exception {
if(args.length != 2) {
System.out.println("arguments: sourcefile destfile");
System.exit(1);
}
FileChannel
in = new FileInputStream(args[0]).getChannel(),
out = new FileOutputStream(args[1]).getChannel();
ByteBuffer buffer = ByteBuffer.allocate(BSIZE);
while(in.read(buffer) != -1) { //buffer 用来向FileChannel读取数据
//其实此循环只会执行一次,因为执行一次就会把FileChannel中的全部数据都读到buffer中
buffer.flip(); // 为通道写入做准备
out.write(buffer); //buffer 用来向FileChannel写入数据
buffer.clear(); // 为通道再次读取做准备
}
}
} ///:~
============================启示================================
当对flip(),clear(),remind()不是很理解而正在考虑某个地方是否需要这三个方法时,我们还可以调用limit(),position(),remainning()等方法来进行调试。
public final int limit()
返回此缓冲区的限制。
public final int position()
返回此缓冲区的当前位置。
public final int remaining()
返回当前位置与限制之间的元素数。
======================================================================
上面的两个例子,是因为有FileChannel的read()或者write(),以至把ByteBuffer中的位置移动了相应的字节数。然后调用flip时,就把限制设置为当前位置。此时的position就不为0了。下面的例子中,没有FileChannel的参与,当前位置也就没有了变化,此时,若再调用flip,由于当前位置是0,设置为限制后,限制也变成0,若我们要从限制为0的ByteBuffer中读取数据,此时就什么也没读到,可能还会抛出异常。那么解决的方法就是调用rewind(),此方法,只是把位置设置为0,而不会改变其限制,这时,限制就仍为容量。因为用ByteBuffer的static allocated()时,新缓冲区的位置将为零,其限制将为其容量!
另外,调用ByteBuffer的get()与put()时,会把position移动一个字节!而调用这两个方法的带参数版本则不会改变position的值,这里还要区别一下两种情况的put方法:
情况一:
ByteBuffer bb = ByteBuffer.allocate(1024);
CharBuffer cb = bb.asCharBuffer(); //创建ByteBuffer的Char视图
cb.put("Hwdy!"); ////字符串中的每个字符占1个字节!共占5个字节!所以此句会使position移动5个字节!
===================================================================
情况二:
ByteBuffer bb = ByteBuffer.allocate(BSIZE);
bb.asCharBuffer().put("Howdy"); //用这种形式来创建视图不会移动bb的position
print(bb.position()); //所以此处的postion值为0
发表评论
-
Velocity读取模板文件的方法[转]
2012-10-30 11:04 1707我用的是velocity-1.6.4,官方自带的Example ... -
jdbc-odbc连接dbf (转)
2011-12-21 12:06 4879dbf分两种,一种是Dbase,另一种是Foxpro的 1、 ... -
jar文件数字签名
2010-10-09 11:45 6415给JAR文件数字签名 1、用keytool生成密钥: k ... -
JAVA国际化配置
2010-09-13 11:03 1220国际化(Internationalization,又称il ... -
dom XML操作
2010-09-10 17:56 892一、创建XML文件 public static vo ... -
轻松部署Java Web Start
2010-07-24 23:19 1338Java Web Start(以下简称JWS)是SUN提供 ... -
调整bufferedimage大小
2010-03-09 19:58 2631/** * 调整bufferedim ... -
jcomboBox显示长项目的内容
2010-03-04 11:19 4420如果JComboBox列表中的内容过长的话,下拉框中不全部显示 ... -
JFreeChart中文使用文档
2010-03-01 16:41 1285JFreeChart类: void setAntiAlias ... -
java crash详细分析
2010-01-30 17:02 2892一. 如何得到这个日志 ... -
JComboBox实现下拉框向上显示
2009-10-24 21:42 5600JComboBox 向上弹出 写一个东西用到了 JComboB ... -
生成验证图片
2009-10-22 21:08 861private void createImage( ... -
发送邮件
2009-10-22 17:08 1030//发送邮件方法 public stat ... -
树节点状态的保存和加载
2009-10-22 10:46 1241保存树节点状态至数据库表中 this.addWindow ... -
jtable添加行标题
2009-10-15 16:11 5159将表格的第一列作为表头,使用渲染器改变其外观,看起来像表头 ... -
修改树节点
2009-10-14 17:40 1322修改jtree树节点时,需要先注册树节点的编辑事件,然后在编辑 ... -
拖拽表数据实现数据的传输
2009-10-14 17:33 1017将表中一条记录拖拽至树中节点时需在表中监听TransferHa ... -
使用序列化实现对象深拷贝
2009-10-14 17:28 1727实现树节点的深拷贝 public DefaultM ... -
JTable 实用方法
2009-09-03 23:11 13601. 设置指定行的颜色 class TableCo ... -
Double精度的常用设置
2009-08-31 23:54 9057import java.text.DecimalFormat; ...
相关推荐
ByteBuffer的用法是Java NIO学习中的核心内容。 首先,我们了解下ByteBuffer的基本概念。ByteBuffer是一个字节缓冲区,可以存储字节序列。在NIO中,所有的数据读写都通过缓冲区进行,ByteBuffer与其他类型的Buffer...
### Java学习笔记知识点总结 #### 一、JVM与内存管理 **1.1 JVM基本概念** - **JVM(Java Virtual Machine)**: Java虚拟机是执行Java字节码的虚拟机,它提供了运行Java程序所需的环境。 **1.2 线程** - **线程...
### Java NIO 学习笔记 #### 一、概述 Java NIO (Non-Blocking IO,也称为 Java New IO),是 Java 对传统 IO 模型的一次重大改进,旨在提高程序处理大量并发连接的能力。NIO 的核心组件包括 Channels、Buffers 和 ...
在`CoreJava_day21`的学习笔记中,主要探讨了Java中的NIO(New I/O)包及其关键类和接口,包括`ByteBuffer`、`FileChannel`以及网络编程中常用的`ServerSocket`和`Socket`等。NIO自JDK 1.4引入以来,因其高效性和...
在MINA的学习笔记中,记录的所有API通常会包括以下几个核心部分: 1. **IoSession**: 这是MINA的核心接口,代表了客户端和服务器之间的连接。IoSession提供了读写数据、管理连接状态、获取会话属性等功能。例如,`...
在这个"Apache MINA2学习笔记DEMO"中,我们很可能会看到如何使用MINA来创建一个自定义协议的示例。自定义协议通常是为了满足特定应用的需求,例如高效的数据传输、安全性或者特定的编码格式。MINA允许开发者定义自己...
ByteBuffer buffer = ByteBuffer.allocate(1024); while (true) { buffer.clear(); int r = fcin.read(buffer); if (r == -1) { break; } buffer.flip(); fcout.write(buffer); } } } ``` 在这个例子...
《NIO学习笔记》 在Java编程领域,NIO(Non-blocking Input/Output,非阻塞I/O)是一种重要的I/O模型,与传统的BIO(Blocking I/O)相对应。NIO提供了一种新的方式来处理I/O操作,特别是在处理大量并发连接时,它的...
在NIO中,有多种类型的缓冲区,如ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer和LongBuffer,分别对应不同的数据类型。缓冲区具有容量、限制和位置等属性,它们控制着数据的读写。在读取数据时,...
了解以上知识点是掌握Apache MINA的基础,通过提供的学习资料,如《Mina2.0学习笔记》、《Apache MINA入门基础》和《Apache MINA Server 2.0中文参考手册》等,可以深入学习MINA的API用法、设计原理和最佳实践。...
这个“learning-netty.zip”压缩包包含了一份Netty的学习笔记,重点在于代码学习和源码分析,基于Netty的4.1版本。下面将围绕Netty的核心概念、特性、以及如何通过学习笔记来深入理解Netty进行详细阐述。 1. **...
这个“自动Netty笔记111”可能是某个开发者或学习者记录的一系列关于Netty学习过程中的关键点和理解。下面将详细阐述Netty的相关知识点。 1. **异步事件驱动模型**: Netty采用了非阻塞I/O模型,基于Java NIO(Non...
这个“netty资料.rar”压缩包文件包含了关于Netty的学习笔记,可以帮助我们深入了解Netty的核心概念和使用技巧。 Netty 的主要特点包括: 1. **异步事件驱动**:Netty 使用了非阻塞I/O模型,基于Java NIO(非阻塞...
在实战笔记中,你可能会学习到如何构建服务器和客户端的Bootstrap,设置连接参数,以及添加处理器链。处理器链(Pipeline)是Netty中事件处理的流水线,每个处理器负责处理特定类型的事件或转换数据。 项目实战部分...
### Mina2.0阅读源码笔记知识点梳理 #### 一、Mina 概述与官方资源 **Mina** 是 Apache 基金会下的一个开源项目,它为开发者提供了一个高性能且易于使用的网络应用框架。Mina 的设计目标是帮助用户轻松地开发出高...
Buffer是存储数据的容器,Java NIO提供了一系列不同类型的Buffer,如ByteBuffer、CharBuffer、IntBuffer等,它们都继承自抽象类Buffer。Selector允许单线程监控多个通道的事件,提高了程序的并发性能。 1. Channel...
这个“Netty-learn”项目显然是一份关于Netty的学习笔记,记录了作者在探索Netty框架过程中的理解和实践。下面将详细阐述Netty的核心概念和重要特性,以及它在网络编程中的应用。 Netty 的主要特点: 1. **异步...
在 "boy-learning-netty-master" 这个压缩包中,很可能是包含了一个个人学习 Netty 的项目或笔记,包含了源码分析、实践示例等内容。通过阅读和研究这些材料,你将能够更深入地理解和运用 Netty,提升你的网络编程...