public class TestIO {
public static void main(String[] args) {
long beginTime = System.currentTimeMillis();
String ZIP_FILE = "1023.zip";
File zipFile = new File(ZIP_FILE);
File src = new File("F:\\person_code\\jvm_deep_base\\module04\\src\\main\\java\\jdk1.8.0_291.zip");
try (// 在这里声明资源,jdk1.7以后会自动关闭关闭资源
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
InputStream inputStream = new FileInputStream(src);) {
zipOut.putNextEntry(new ZipEntry("1023.zip"));
int trans = 0;
while ((trans = inputStream.read()) != -1) {
zipOut.write(trans);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("文件大小: " + src.length());
System.out.println("耗时: " + (System.currentTimeMillis() - beginTime));
}
}


 使用字节输入输出流进行I/O拷贝,传输单位是一个字节,速度缓慢。

压缩文件,IO拷贝优化。_零拷贝



public class TestIO2 {
public static void main(String[] args) {
String ZIP_FILE = "1023.zip";
File zipFile = new File(ZIP_FILE);
File src = new File("F:\\person_code\\jvm_deep_base\\module04\\src\\main\\java\\jdk1.8.0_291.zip");
long beginTime = System.currentTimeMillis();
try (
// jdk以后 这里声明的变量会自动关闭申请的资源
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(zipOut);
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(src));
) {
zipOut.putNextEntry(new ZipEntry("1023.zip"));
int trans = 0;
while ((trans = bufferedInputStream.read()) != -1) {
bufferedOutputStream.write(trans);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("文件大小: " + src.length());
System.out.println("耗时: " + (System.currentTimeMillis() - beginTime));
}
}


使用字节缓冲输入输出流进行I/O拷贝,传输单位是一个字节,速度缓慢。例如我们现在有30000个字节的数据,如果使用 ​​FileInputStream​​那么就需要调用30000次的本地方法来获取这些数据,而如果使用缓冲区的话(这里假设初始的缓冲区大小足够放下30000字节的数据)那么只需要调用一次就行。

 压缩文件,IO拷贝优化。_输入输出流_02



public class TestIO3 {
public static void main(String[] args) {
String ZIP_FILE = "1023.zip";
File zipFile = new File(ZIP_FILE);
File src = new File("F:\\person_code\\jvm_deep_base\\module04\\src\\main\\java\\jdk1.8.0_291.zip");
long beginTime = System.currentTimeMillis();
try (
// jdk以后 这里声明的变量会自动关闭申请的资源
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
WritableByteChannel writableByteChannel = Channels.newChannel(zipOut);
FileChannel channel = new FileInputStream(src).getChannel();
) {
zipOut.putNextEntry(new ZipEntry("1023.zip"));
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (channel.read(buffer) != -1) {
buffer.flip();
writableByteChannel.write(buffer);
buffer.clear();
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("文件大小: " + src.length());
System.out.println("耗时: " + (System.currentTimeMillis() - beginTime));
}
}


NIO中新出了 ​​Channel​​和 ​​ByteBuffer​​。正是因为它们的结构更加符合操作系统执行I/O的方式,所以其速度相比较于传统IO而言速度有了显著的提高。​​Channel​​就像一个包含着煤矿的矿藏,而 ​​ByteBuffer​​则是派送到矿藏的卡车。也就是说我们与数据的交互都是与 ​​ByteBuffer​​的交互。

 压缩文件,IO拷贝优化。_java_03



public class TestIO4 {
public static void main(String[] args) {
String ZIP_FILE = "1023.zip";
File zipFile = new File(ZIP_FILE);
File src = new File("F:\\person_code\\jvm_deep_base\\module04\\src\\main\\java\\jdk1.8.0_291.zip");
long beginTime = System.currentTimeMillis();
try (
// jdk以后 这里声明的变量会自动关闭申请的资源
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
WritableByteChannel writableByteChannel = Channels.newChannel(zipOut);
FileChannel channel = new FileInputStream(src).getChannel();
) {
zipOut.putNextEntry(new ZipEntry("1023.zip"));
channel.transferTo(0, src.length(), writableByteChannel);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("文件大小: " + src.length());
System.out.println("耗时: " + (System.currentTimeMillis() - beginTime));
}
}


 使用 ​​transferTo​​的效率比循环一个 ​​Channel​​读取出来然后再循环写入另一个 ​​Channel​​好。操作系统能够直接传输字节从文件系统缓存到目标的 ​​Channel​​中,而不需要实际的 ​​copy​​阶段。简单来说省去了从内核空间转到用户空间的一个过程。