Java: NIO和NIO.2之间到底有什么区别?

94

我对于这两个包的不同并不是很清楚,所以我有一些关于这两个包的问题。

在 Google 上查阅了一下后,似乎 Oracle 决定将 NIO 包更新为 JDK7 发布的新版和增强版的 NIO.2 包。

  1. NIO 包与 NIO.2 包的性能如何相比?
  2. NIONIO.2 有哪些重大变化?(例如:新增方法、特性)
  3. 为什么原始的 NIO 包需要进行更新?
  4. 现在 NIO.2NIO 包是否意味着相同?

并不是因为我想在我的代码中使用旧版本的包,而是我非常好奇它们之间的区别,请告诉我它们的不同之处。


2
NIO2引入了异步I/O和java.nio.files包。 - user207421
就这样?我一直以为NIO.2是一件很大的事情。 - John Huynh
1
首先,他们有了IO。然后,他们引入了"New IO"。接着,他们想要引入更多的功能,于是巧妙地将其命名为"New IO 2"。 - Kayaman
1
谢谢,我明白了。那是否意味着"New IO 2"在所有方面都优于其他两个?我正在阅读《Java教程》这本书,它讲解了NIO.2,但也有关于IO的部分。 - John Huynh
2
@JohnHuynh 不,这意味着它引入了新功能。如果您不需要它们,请勿使用它们。 - user207421
3个回答

95

Java最初提供了位于java.io包中的File类来访问文件系统。该对象表示文件/目录,并允许您执行某些操作,例如检查文件/目录是否存在、获取属性和删除它。然而,它也存在一些缺点:

  • File类缺乏一些重要功能,例如拷贝方法。
  • 它还定义了许多返回boolean的方法。可以想象,在出现错误的情况下,将返回false而不是抛出异常。开发者实际上无法知道为什么会失败。
  • 没有提供对符号链接的良好处理支持。
  • 提供了有限的文件属性集。

为了克服这些问题,Java 4中引入了java.nio包。其主要特点包括:

  • 通道和选择器:通道是较低级别文件系统特性的抽象,例如内存映射文件。
  • 缓冲区:用于所有基本类(布尔值除外)的缓冲。
  • 字符集:字符集(java.nio.charset)、编码器和解码器,用于映射字节和Unicode符号。

随着Java 7的推出,java.nio.file包提供了更好的符号链接处理、文件属性访问以及特别支持通过Path、Paths和Files等类扩展文件系统。您可能想查看java.nio.file包描述以获取更多详细信息。

有了这个基础,

NIO和NIO.2有哪些重大变化(例如新增的方法、功能)?

它们服务于不同的目的。要指出主要变化,您可能需要查看全新的java.nio.file包。

为什么原始的NIO包必须更新?

它没有必要更新。而是引入了一个新的包。

NIO.2现在是否只是与NIO包同义词? NIO包的性能如何与NIO.2包相比较? 不,它们不是同义词。将它们的性能进行比较也没有太多意义,因为它们有不同的用途。NIO更抽象的低级数据输入/输出,而NIO.2则专注于文件管理。[参考文献:Oracle Certified Professional Java SE7-全面的OCJP7认证指南,作者S.G.Ganesh和Tushar Sharma——第9章]

67

NIO.2引入了异步I/O

异步I/O是一种非阻塞I/O的方法,而NIO不支持此方法。

NIO:选择器/反应器模式

NIO.2:完成处理程序/主动通知模式

因此,在Windows上,NIO.2使用I/O完成端口,这应该可以提高性能。但是,没有人知道,因为在服务器端没有人使用Windows,如果他们这样做,他们可能会因为深度投资于.net而这样做,并且出于这个原因,很可能不会考虑使用Java。


3
永远不要说永远。特别是在预计工作负载不高时,许多基于Windows的服务器正在使用中。 - Jonathan Rosenne
反应式设计模式与前置条件模式是我最注意到的。 - Lefteris Eleftheriades
3
我们公司是一家领先的金融机构,拥有大量的Windows服务器,主要使用Java。 - Janac Meena

12

我的看法:

简短版本

它是添加了java.nio.file包及其更高级的文件和文件系统功能。
从网络套接字或低级文件访问角度来看,NIO == NIO.2,只有一些方便的改进。

较长版本

Java IO

包: java.io
旧的阻塞I/O API。

Java NIO

在Java 1.4中添加了新的非阻塞API。
包: java.nio
Java非阻塞I/O。类似于SelectorSelectorKeyChannel等。
在我看来,对于网络I/O(SelectorSelectorKeySocketChannelServerSocketChannelBuffer),NIO是一个重大的进步,但对于文件I/O(仅限于FileChannelBuffer,包括内存映射文件),则不太明显。 这是一个相当低级别的API,适用于网络和文件部分。

Java NIO.2

在Java 7中添加。它主要是关于添加了更强大的文件和文件系统操作API。新的文件和文件系统相关API是相对较高级别的。

包: java.nio.file和一些对父类java.nio的补充。
这些补充只适用于文件I/O,对于网络I/O或低级文件API仅有少量的补充。

最引人注目的低层次、与文件无关的API增加内容是AsynchronousSocketChannelAsynchronousServerSocketChannelAsynchronousFileChannel,这些为一些方法添加了回调变体。异步版本主要是一种方便的补充;即使在此之前也可以组合这样的映射接口,但现在它们在JRE中已经可以直接使用。
新的文件API带来了很多好处——使用Path进行更有用的文件系统寻址,使用自定义文件系统提供程序进行更改进的ZIP文件操作,访问特殊文件属性,以及许多方便的方法,例如使用一个命令读取整个文件,使用一个命令拷贝文件等。但这些都与文件/文件系统相关,而且都非常高级。
重申我以上所说的,在网络套接字或低级文件访问的角度来看,NIO == NIO.2
相关链接:
  • https://docs.oracle.com/javase/7/docs/technotes/guides/io/enhancements.html#jdk7 - 仅在NIO.2章节下提及与文件相关的更改。

  • 网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接