Java NIO入门
NIO入门
前段时间在公司里处理一些大的数据,并对其进行分词、提取关键字等。虽说任务基本完成了(效果也不是特别好),对于Java还没入门的我来说前前后后花了2周的时间,我自己也是醉了。当然也有涉及到机器学习的知识,我想陆陆续续的记录下我的这一次任务的过程,也算做一个总结。
首先,手上有这么个达G级别的文件,按照Java普通I/O的方式肯定是不行的了,划分文件的话,也不知何年何月才能读完。所以后来上网查找了相关资料,才知道有这么个神奇的NIO。
在Java编程中,I/O是用流的方式读取文件,所有I/O都被视为单个的字节的移动,通过一个称为Stream的对象一次移动一个字节。Java中新的输入/输出(NIO)库是在JDK1.4中引入的。NIO弥补了原来I/O的不足,它在标准Java代码中提供了高速、面向块的I/O。通过定义包含数据的块,以及通过以块的形式来处理这些数据,NIO不用使用本机代码就可以利用低级优化,这是原来的I/O包所无法做到的。
流与块的比较
原来的I/O库和NIO最重要的区别就是数据打包和传输的方式,原来的I/O以流的方式处理数据,而NIO以块的方式处理数据。
面向流的I/O系统一次一个字节的处理数据,一个输入流产生一个字节的数据,一个输出流产生一个字节的数据。
一个面向块的I/O系统以块的形式处理数据。每一个操作都在一步中产生或者消费一个数据块。按块处理数据比按字节处理数据要快得多,即便它没有面向流的I/O那样的简单性。
通道和缓冲区
通道和缓冲区是NIO中的核心对象,几乎在每一个I/O操作中都要使用它们。
通道是对原I/O包中的流的模拟。到任何目的地或来自任何地方的所有数据都必须通过一个Channel对象。一个Buffer实质上是一个容器对象。发送给一个通道的所有对象都必须首先存放到缓冲区中;同样的,从通道中读取任何的数据都必须首先读取到缓冲区里。
什么是缓冲区?
Buffer是一个对象,它包含一些要写入或者刚读出的数据。 在 NIO 中加入Buffer对象,体现了新库与原 I/O 的一个重要区别。在面向流的 I/O 中,您将数据直接写入或者将数据直接读到Stream对象中。在 NIO 库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问 NIO 中的数据,您都是将它放到缓冲区中。缓冲区实质上是一个数组。通常它是一个字节数组,但是也可以使用其他种类的数组。但是一个缓冲区不仅仅是一个数组。缓冲区提供了对数据的结构化访问,而且还可以跟踪系统的读/写进程。
缓冲区类型
最常用的缓冲区类型是ByteBuffer。一个ByteBuffer可以在其底层字节数组上进行 get/set 操作(即字节的获取和设置)。ByteBuffer不是 NIO 中唯一的缓冲区类型。事实上,对于每一种基本 Java 类型都有一种缓冲区类型:
ByteBuffer
CharBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
每一个Buffer类都是Buffer接口的一个实例。 除了ByteBuffer,每一个 Buffer 类都有完全一样的操作,只是它们所处理的数据类型不一样。因为大多数标准 I/O 操作都使用ByteBuffer,所以它具有所有共享的缓冲区操作以及一些特有的操作。
下面看一下FloatBuffer的简单例子:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.channels.FileChannel; // UseFloatBuffer public class UseFloatBuffer { public static void main(String[] args) throws Exception { FloatBuffer fb=FloatBuffer.allocate(10);
for (int i=0; i<fb.capacity(); i++) {
float f=(float)((float)i/10*(2*Math.PI));
fb.put(f);
}
fb.flip();
while (fb.hasRemaining()){
float f=fb.get();
System.out.println(f);
}
}
}
什么是通道?
Channel是一个对象,可以通过它读取和写入数据。拿 NIO 与原来的 I/O 做个比较,通道就像是流。正如前面提到的,所有数据都通过 Buffer 对象来处理。您永远不会将字节直接写入通道中,相反,您是将数据写入包含一个或者多个字节的缓冲区。同样,您不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。简而言之,就是NIO的大致流程为:输入文件->缓冲区->通道->缓冲区->程序处理数据->缓冲区->通道->缓冲区->输出文件;I/O的大致流程为:输入文件->流->程序处理数据->流->输出文件。
通道类型
通道与流的不同之处在于通道是双向的。而流只是在一个方向上移动(一个流必须是InputStream或者OutputStream的子类),而通道可以用于读、写或者同时用于读写。
实践起来:NIO 中的读和写
读和写是 I/O 的基本过程。从一个通道中读取很简单:只需创建一个缓冲区,然后让通道将数据读到这个缓冲区中;写入也相当简单:创建一个缓冲区,用数据填充它,然后让通道用这些数据来执行写入操作。
从文件中读取
如果使用原来的 I/O,那么我们只需创建一个FileInputStream并从它那里读取。而在 NIO 中,情况稍有不同:我们首先从FileInputStream获取一个Channel对象,然后使用这个通道来读取数据。
在 NIO 系统中,任何时候执行一个读操作,您都是从通道中读取,但是您不是直接从通道读取。因为所有数据最终都驻留在缓冲区中,所以您是通过通道读到缓冲区中的数据。
因此读取文件涉及三个步骤:
(1) 从FileInputStream获取Channel
(2) 创建Buffer
(3) 将数据从Channel读到Buffer中。
FileInputStream fin=new FileInputStream("read.txt");
FileChannel fc=fin.getChannel();
ByteBuffer buffer=ByteBuffer.allocate(1024);
fc.read(buffer);
写入文件
在 NIO 中写入文件类似于从文件中读取。首先从FileOutputStream获取一个通道;下一步是创建一个缓冲区并在其中放入一些数据 - 在这里,数据将从一个名为data的数组中取出,最后一步是写入缓冲区中。
FileOutputStream fout=new FileOutputStream("write.txt");
FileChannel fc=fout.getChannel();
ByteBuffer buffer=ByteBuffer.allocate(1024);
for (int i=0; i<data.length; i++) {
buffer.put(data[i]);
}
buffer.flip();
fc.write(buffer);
实战练习
我们以一个名为 CopyFile.java 的简单程序作为这个练习的基础,它将一个文件的所有内容拷贝到另一个文件中。CopyFile.java 执行三个基本操作:首先创建一个Buffer,然后从源文件中将数据读到这个缓冲区中,然后将缓冲区写入目标文件。这个程序不断重复 ― 读、写、读、写 ― 直到源文件结束。
// CopyFile import java.io.*;
import java.nio.*;
import java.nio.channels.*; public class CopyFile { static public void main( String args[] ) throws Exception {
String infile="E:\\北京欢迎你.txt";
String outfile="E:\\out.txt"; FileInputStream fin=new FileInputStream(infile);
FileOutputStream fout=new FileOutputStream(outfile);
FileChannel fcin = fin.getChannel();
FileChannel fcout = fout.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(1024); while (true) {
buffer.clear();
int r=fcin.read(buffer);
if (r == -1) {
break;
}
buffer.flip();
fcout.write(buffer);
}
}
}


Java NIO入门的更多相关文章
- Java NIO入门(二):缓冲区内部细节
Java NIO 入门(二)缓冲区内部细节 概述 本文将介绍 NIO 中两个重要的缓冲区组件:状态变量和访问方法 (accessor). 状态变量是前一文中提到的"内部统计机制"的 ...
- 史上最强Java NIO入门:担心从入门到放弃的,请读这篇!
本文原题“<NIO 入门>,作者为“Gregory M. Travis”,他是<JDK 1.4 Tutorial>等书籍的作者. 1.引言 Java NIO是Java 1.4版 ...
- Java NIO 入门
本文主要记录 Java 中 NIO 相关的基础知识点,以及基本的使用方式. 一.回顾传统的 I/O 刚接触 Java 中的 I/O 时,使用的传统的 BIO 的 API.由于 BIO 设计的类实在太 ...
- java NIO入门【原】
server package com.server; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import jav ...
- Java NIO入门小例(短连接:客户端和服务器一问一答)
例子中有些写法参考自Netty4源码,建议在实际运用中采用Netty,而非原生的Java NIO(小心epoll空转). 1. 服务器端 public class NioServer { static ...
- Java nio 笔记:系统IO、缓冲区、流IO、socket通道
一.Java IO 和 系统 IO 不匹配 在大多数情况下,Java 应用程序并非真的受着 I/O 的束缚.操作系统并非不能快速传送数据,让 Java 有事可做:相反,是 JVM 自身在 I/O 方面 ...
- Java Socket NIO入门
Java Socket.SocketServer的读写.连接事件监听,都是阻塞式的.Java提供了另外一种非阻塞式读写.连接事件监听方式——NIO.本文简单的介绍一个NIO Socket入门例子,原理 ...
- JAVA NIO异步通信框架MINA选型和使用的几个细节(概述入门,UDP, 心跳)
Apache MINA 2 是一个开发高性能和高可伸缩性网络应用程序的网络应用框架.它提供了一个抽象的事件驱动的异步 API,可以使用 TCP/IP.UDP/IP.串口和虚拟机内部的管道等传输方式.A ...
- Mina入门:Java NIO基础概念
JDK1.4引入了Java NIO API(Java New IO),Java NIO得到了广泛应用.NIO允许程序进行非阻塞IO操作.java.nio.* 包括以下NIO基本结构: Buffer - ...
随机推荐
- python反转字符串(简单方法)及简单的文件操作示例
Python反转字符串的最简单方法是用切片: >>> a=' >>> print a[::-1] 654321 切片介绍:切片操作符中的第一个数(冒号之前)表示切片 ...
- .NET生成缩略图并下载
缩略图:比喻一张图片宽度为1000px,大小为800K,经过缩略后变成一张宽度100px,大小10K的图片. 先给出界面: 总体的流程分5步如下图: 1.添加一个html:GetminPic.html ...
- C#设计模式——状态模式(State Pattern)
一.概述在面向对象软件设计时,常常碰到某一个对象由于状态的不同而有不同的行为.如果用if else或是switch case等方法处理,对象操作及对象的状态就耦合在一起,碰到复杂的情况就会造成代码结构 ...
- [CLR via C#]13. 接口
一.类和接口继承 在Microsoft.Net Framwork中,有一个名为System.Object的类,它定义了4个公共实例方法:ToString, Equals, GetHashCode和Ge ...
- SqlServer定时备份数据库和定时杀死数据库死锁解决
上周五组长对我说了一句要杀死数据库的死锁进程,有时候同一时刻不停写入数据库会造成这种情况的发生,因为自己对数据库不是很熟悉,突然组长说了我也就决定一定要倒腾一下,不然自己怎么提高呢?现在不研究,说不定 ...
- 机器学习实战 - 读书笔记(07) - 利用AdaBoost元算法提高分类性能
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习笔记,这次是第7章 - 利用AdaBoost元算法提高分类性能. 核心思想 在使用某个特定的算法是, ...
- Android应用开发基础之四:网络编程(一)
网络图片查看器 确定图片的网址 发送http请求 URL url = new URL(address); //获取连接对象,并没有建立连接 HttpURLConnection conn = (Http ...
- Smtp邮件发送系统公用代码整理—总结
1.前言 a.在软件开发中,我们经常能够遇到给用户或者客户推送邮件,推送邮件也分为很多方式,比如:推送一句话,推送一个网页等等.那么在系统开发中我们一般在什么情况下会使用邮件发送呢?下面我简单总结了一 ...
- css3属性(一)
圆角效果: border-radius: 5px 4px 3px 2px; /* 四个半径值分别是左上角.右上角.右下角和左下角,顺时针 */ 阴影: box-shadow:X轴偏移量 Y轴偏移量 [ ...
- ABAP - 3D Graphs with SAP
在ABAP设计中,程序员经常需要用图形显示报表的统计结果,我们可以使用函数:GRAPH_MATRIX_3D来达到图形显示.GRAPH_MATRIX_3D函数参数很多,但只有三个参数必须需要输入:Tab ...