一、IO和NIO的区别
1、io和nio无非是对数据进行读取和写入操作,但是io是将流中的数据读取到内存,或者写入到磁盘。而nio是将通道channel中的数据读取到缓冲区buffer或者,将buffer的数据写入到channel中。
(1)、进行io操作时,如读取文件,io会处于阻塞状态直到有数据可读。此时cpu多数时间处于空闲状态,浪费了cpu时间片的资源。而Nio可以设置channel为非阻塞状态,并且可以开启多个线程同时进行读写操作,此时节约cpu时间片的资源,但是cpu一直运转增大了内存消耗,并且增大了线程切换的开销。每个线程内部都是一个私有的程序计数器,会记录程序运行的位置,从而保证线程顺利切换。
(2)、Nio大大提高了io的执行速度。Nio可以同时将一个channel中的数据读入到多个Buffer中,也可以同时多个Buffer中的数据同时写入到同一个channel中。并且Nio的选择器Selector在开启一个线程的情况下,可以同时注册多个channel并对其监控。而io实现这个功能则需要开启多个线程。
二、io部分基础复习
1、RandomAccessFile、File的使用
RandomAccessFile是一个具有强大功能来操作文件的类
(1)复制文件
<span style="font-family:KaiTi_GB2312;">package testFile;
import java.io.File;
import java.io.RandomAccessFile;
public class TestRandomAccessFile {
public static void main(String[] args) throws Exception {
File file1 = new File("file1.txt");
File file2 = new File("file2.txt");
copyFile(file1, file2);
}
public static void copyFile(File file1, File file2) throws Exception {
if (!file2.exists()) {
file2.createNewFile();
}
RandomAccessFile rf1 = new RandomAccessFile(file1, "r");//r只读模式获取
RandomAccessFile rf2 = new RandomAccessFile(file2, "rw");//读写模式获取
rf1.getFilePointer();//获取当前指针的位置
rf1.seek(11);//设置指针位置为11,读取时会从指针当前位置开始
byte[] content = new byte[48];
int len = 0;//有效长度
while((len = rf1.read(content)) != -1) {
rf2.write(content,0,len);
}
rf2.close();
rf1.close();
}
}
</span>
file1.txt文件内容为:
hello wolrd
这是演示文本!!!
file2.txt文件内容为:
这是演示文本!!!
这是因为指针刚好移动11个字节,从第二行开始读取。
(2)、通过File遍历目录下的所有子目录并输出
<span style="font-family:KaiTi_GB2312;">public class TestFile {
public static void main(String[] args) {
String fileName = "F:\\aspectj-1.8.9\\$installer$";
File file = new File(fileName);
listFile(file);
}
public static void listFile(File file) {
if(file.isDirectory()) {
File[] files = file.listFiles();
for(File f:files) {
listFile(f);
}
}else {
System.out.println(file.getName());
}
}
}</span>
(3)、多个线程间用io流进行通信
<span style="font-family:KaiTi_GB2312;">package testFile;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.Scanner;
public class TestPiped {
public static void main(String[] args) {
Sender sender = new Sender();
Receiver receiver = new Receiver();
try {
//对象初始化之后,将这两个流通过connect连接成一个管道
receiver.pStream.connect(sender.pStream);
} catch (IOException e) {
System.out.println(e.getMessage());
}
sender.start();
receiver.start();
}
}
class Sender extends Thread {
PipedOutputStream pStream = null;
public Sender() {
pStream = new PipedOutputStream();
}
@Override
public void run() {
System.out.print("請輸入要說的:");
Scanner sc = new Scanner(System.in);
String msg = sc.nextLine();
try {
pStream.write(msg.getBytes());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
class Receiver extends Thread {
PipedInputStream pStream = null;
public Receiver() {
pStream = new PipedInputStream();
}
@Override
public void run() {
try {
byte[] b = new byte[1024];
int len = 0;
while ((len = pStream.read(b)) != -1) {
System.out.println(new String(b, 0, len) + "这是该线程接收到的数据");
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}</span>
测试结果:
請輸入要說的:管道流測試數據
管道流測試數據这是该线程接收到的数据
Write end dead
三、Nio核心知识
缓冲区Buffer、通道Channel、选择器Selector将在后面依次介绍。