jdK1.4的java.nio.*包中引入了JavaI/O类库,其目的在于提高速度。实际上,旧的I/O包已经使用nio重新实现过,以便充分利用这种速度提高,因此,即使我们不显示的用nio编写代码,也能从中受益。
速度的提高来自于所使用的结构更加接近操作系统执行I/O的方式:通道和缓冲器。我们可以把它想象成一个煤矿,通道是一个包含煤层(数据)的矿藏,而缓冲器则是派送到矿藏的卡车。卡车载满煤炭而归,我们再从卡车上获得煤炭。也就是说,我们并没有直接和通道打交道,我们只是和缓冲器交互,并把缓冲器派送到通道。通道要么从缓冲器获得数据,要么向缓冲器发送数据。
唯一直接与通道交互的缓冲器是ByteBuffer---也就是说,可以存储未加工字节的缓冲器。当我们查询JDK文档中的java.nio.ByteBuffer时,会发现它是相当基础的类:通过告知分配多少存储空间来创建一个ByteBuffer对象,并且还有一个方法选择集,用于以原始的字节形式或基本数据类型输出和读取数据。但是,没有办法输出或读取对象,即使是字符串对象也不行。这种处理虽然很低级,但却正好,因为这是大多数操作系统中更有效的映射方式。
旧的IO类库有三个类被修改,用以产生FileChannel(用于读取、写入、映射和操作文件的通道)。这三个被修改的类是FileInputStream、FileOutputStream以为用于既读又写的RandomAccessFile。注意这些是字节操纵流,与低层的nio性质一致。Reader和Writer这种字符模式类不能用于产生通道;但是java.nio.channels.Channels类提供类实用方法,用以在通道中产生Reader和Writer。
下面的简单实例演示了上面三种类型的流,用以产生可以写的、可读可写的及可读的通道。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class GetChannel {
private static final int BSIZE = 1024;
public static void main(String[] args) throws IOException{
//write a file
FileChannel fc = new FileOutputStream("data.txt").getChannel();
fc.write(ByteBuffer.wrap("hello world".getBytes()));
fc.close();
//加到文件末尾
fc = new RandomAccessFile("data.txt", "rw").getChannel();
fc.position(fc.size()); //移到文件末尾用position方法
fc.write(ByteBuffer.wrap(" hello world again".getBytes()));
fc.close();
//读取文件
fc = new FileInputStream("data.txt").getChannel();
ByteBuffer buffer = ByteBuffer.allocate(BSIZE);
fc.read(buffer); //通道从缓冲器中读取内容
buffer.flip(); //读了之后要flip一下
while(buffer.hasRemaining())
System.out.print((char)buffer.get());
}
}
对于这里展示的任何流类,getChannel()将会产生一个FileChannel。通道是一种相当基础的东西,可以向它传送关于读写的ByteBuffer。
将字节存放于ByteBuffer的方法之一是:使用“put”方法直接填充,填入一个或者多个字节,或基本数据类型的值。也可以使用wrap()方法将已经存在的字节数组“包装”到ByteBuffer中。
对于只读访问,我们必须显式的使用静态allocate()方法来分配ByteBuffer。nio的目标就是快读移动大量数据,因此ByteBuffer的大小就显得尤为重要。甚至达到更高的速度也有可能,方法就是allocateDirect而不是allocate,以产生一个与操作系统更高耦合性的直接缓冲器。但是,这种分配开支会更大,并且具体实现也随着操作系统的不同而不同。
一旦调用read()来告知FileChannel向ByteBuffer存储字节,就必须调用缓冲器上的flip(),让它做好让别人读取字节的准备。如果我们打算使用缓冲器执行进一步的read()操作,我们必须得调用clear()来为每个read()做好准备。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class ChannelCopy {
private static final int BSIZE = 1024;
public static void main(String[] args) throws IOException{
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.flip(); //prepare for writing
out.write(buffer);
buffer.clear(); //prepare for reading
}
}
}
每次read()操作之后,就会将数据输入到缓冲器中,flip()则是准备缓冲器以便她的信息可以由write()提取。write()操作之后,信息扔存在缓冲器中,接着clear()操作则对所有的内部指针重新安排,以便缓冲器在另一个read()操作期间能够做好接受数据的准备。
然而,上面那个程序并不是处理此类操作的理想方式。特殊方法transferTo()和transferFrom()则允许我们将一个通道和另一个通道直接相连。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
public class TransferTo {
public static void main(String[] args) throws IOException{
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();
in.transferTo(0, in.size(), out);
//或者
out.transferFrom(in, 0, in.size());
}
}
相关推荐
《Java编程思想》是Java程序员领域的一本经典之作,由Bruce Eckel撰写,以其深入浅出的讲解方式和丰富的实例闻名。这本书对于想要深入理解Java语言的人来说,是一份宝贵的资源。"Thinking in Java",直译为“思考...
《Java编程思想》是 Bruce Eckel 的经典著作,第四版更是深入浅出地介绍了Java语言的核心概念和技术。这个压缩包包含的源代码是书中的示例程序,它们旨在帮助读者理解书中阐述的各种编程原理和实践。通过分析这些源...
在Java NIO的实践中,有时会看到`begin()`和`end()`这样的方法对出现,尤其是在涉及并发编程的场景中。 **这些方法的主要用途是:** - **事务控制**:用于确保一系列操作的原子性,即要么全部成功,要么全部失败。...
《JAVA编程思想》是 Bruce Eckel 的经典著作,中文版为国内Java开发者提供了深入理解Java语言的宝贵资源。这本书全面而深入地介绍了Java编程的核心概念和技术,是学习和提升Java编程技能的重要参考资料。 本书主要...
《Java编程思想》是 Bruce Eckel 的著作,它在编程界享有极高的声誉,被誉为Java学习的经典之作。这本书深入浅出地介绍了Java编程语言的核心概念和技术,为读者提供了全面而深刻的Java理解。中文版的清晰度高,使得...
在Java编程领域,掌握《Java编程思想》是深入理解这门语言的重要步骤。这本书由Bruce Eckel撰写,被誉为Java学习者的经典之作。本资源包含了该书第四版的完整练习题答案,旨在帮助读者巩固和深化对书中理论的理解,...
《Java编程思想》是 Bruce Eckel 的经典著作,它深入浅出地介绍了Java语言的核心概念和技术,对于初学者和有经验的程序员来说都是极好的学习资源。这本书从对象的概念出发,逐步引导读者深入理解Java的世界。 1. **...
《Java编程思想习题及答案》是一份针对Java编程学习者的宝贵资源,它包含了大量关于Java编程的习题和对应的解答。这份资料可能是从www.pigkrtv.com等网站转载而来,旨在帮助学习者深化对Java编程语言的理解,提高...
《Java编程思想练习题》是一份宝贵的资源,旨在帮助学习者深入理解和掌握Java编程的核心概念。这份资料可能包含了丰富的编程习题,旨在强化对Java语言的理解,提高编程技能。通过解决这些练习,开发者可以巩固基础...
这本书旨在帮助读者理解和掌握Java的核心编程思想,从而能够运用这些概念来解决实际问题。书中的内容涵盖了Java语言的基础、高级特性以及面向对象编程的精髓。 1. **Java基础**:书中首先介绍了Java语言的基础知识...
总的来说,"tiny-web-server"项目提供了一个学习和实践Java NIO以及服务器端编程的好机会,你可以通过阅读和分析源代码,了解如何利用非阻塞I/O来提高Web服务器的性能,同时也可以借鉴其设计思想,为自己的项目提供...
它要求开发者转变从顺序编程到并发编程的思想,学会识别并利用程序中的并行部分,同时还要学会处理因并发带来的复杂问题。这个过程需要开发者具备高度的耐心和解决问题的能力,以及对细节的充分关注。 综上所述,...
Java编程思想是Java开发者必经的学习之路,尤其对于初学者来说,掌握其核心概念和语法至关重要。本资源“课程—java编程思想3”显然聚焦在深入理解和应用Java编程的高级主题上,它作为纠错版,意味着它可能包含了对...
《Java编程思想》是Bruce Eckel的经典著作,深入浅出地介绍了Java编程语言的核心概念和技术。在学习这本书的过程中,读者经常需要运行书中提供的代码示例。"com.bruceeckel.*(java编程思想需要包)"这个标题暗示了...
在Java编程思想中,主要涵盖了以下几个关键知识点: 1. **基础语法**:Java语言的基础,包括数据类型(基本类型和引用类型)、变量、运算符、流程控制(条件语句和循环)、数组等。理解这些概念是学习Java的第一步...
### 《Java编程思想4》核心知识点概览 #### 一、书籍基本信息 - **书名**:《Thinking In Java 4th》(Java编程思想第四版) - **作者**:Bruce Eckel - **出版社**:MindView, Inc. #### 二、读者评论概述 1. *...
理解类的定义、对象的创建以及封装、继承和多态等概念是Java编程的基础。封装使数据和方法安全,继承则允许代码重用,多态则为程序提供了灵活性。 2. **类和对象**:类是创建对象的蓝图,包含了属性(数据成员)和...
《Java编程思想笔记》是基于 Bruce Eckel 的经典著作 "Thinking in Java" 所做的学习总结,这本书深入浅出地介绍了Java语言的核心概念和技术。在本文中,我们将围绕Java编程的一些关键知识点进行深入探讨,包括但不...
《JAVA 编程思想》是 Bruce Eckel 的经典著作,这本书深入浅出地阐述了Java编程的核心概念和技术,是许多Java开发者入门和进阶的重要参考书籍。书中涵盖了面向对象编程的基本原理、类与对象、继承与多态、接口与抽象...