第一部分 Java I/O入门


第一章 I / O基础知识和API

输入和输出(I/O)设施是操作系统以及计算机语言及其库的基础部分。除了微不足道的计算机程序之外,所有这些程序都执行某种输入或输出操作。

Java始终支持I/O。其初始的I/O和API相关架构被称为经典I/O。由于现在操作系统具有经典I/O不支持的较新的I/O特征,因此Java将新的I/O(NIO)作为JDK 1.4的一部分进行了支持。由于时间关系导致一部分NIO功能没有被包含在JDK 1.4中,因此其他的NIO功能被推迟到了JDK 5和JDK 7中实现了。

本章向您介绍了经典的I/O,NIO和NIO.2。您将了解其所涉及到的基本I/O功能。此外,您将看到他们的API概述。后续章节中会深入了解这些API的功能。

1.1 经典I/O

JDK 1.0引入了用于访问文件系统的基本I/O功能(创建目录,删除文件或执行其他任务),随机访问文件内容(而不是依次访问),并在源和目标之间以顺序的方式传输面向字节的数据 。

1.1.1 文件系统访问和File类

文件系统是管理数据存储和后续检索的操作系统组件。运行Java虚拟机(JVM)的操作系统至少支持一个文件系统。例如,Unix或Linux将所有已安装(已连接和准备好的)磁盘组合到一个虚拟文件系统中。 相比之下,Windows将单独的文件系统与每个活动磁盘驱动器相关联。

文件系统将存有数据的文件存储在目录中, 文件和目录对象可以通过指定的路径来访问。路径是定位文件和标识文件系统对象的关联映射,路径可以是绝对的和相对的:

  • 绝对路径是相对于文件系统根目录的路径。 它表示为根目录符号,后跟目标名称的分隔层次结构,以目标目录或文件名结尾。
  • 相对路径是相对于某个其他目录的路径。它与绝对路径类似,但没有初始根目录符号。 相比之下,它通常以一个或多个分隔的“..”字符序列为前缀,其中每个序列都指父目录。

不同的操作系统路径的表示方式不同。例如,Unix,Linux 和类Unix操作系统中使用正斜杠(/)标识根目录和路径分隔组件,而在Windows中则使用反斜杠(\)。如下两个例子:

# Unix,Linux和类Unix系统中的表示法
/users/username/bin
# Windows系统中的表示法
\users\username\bin

上面两个例子分别是在Unix/Linux环境中访问子目录bin和在Windows中访问子目录bin的方式。

Windows和类似的操作系统可以管理多个文件系统。每个文件系统都使用驱动器说明符(如“C:”)进行标识。 当没有指定驱动器说明符的路径时,该路径是相对于当前文件系统。 否则,它是相对于指定的文件系统 :

\users\username\bin
C:\users\username\bin

第一行访问相对于当前文件系统的路径,而第二行访问相对于C:文件系统的路径 。

java.io.File类的一个实例抽象出文件或目录路径。 此实例提供对文件系统的访问,以执行此路径上的任务,例如删除底层文件或目录。 以下示例演示此类:

new File("temp").mkdir();

该示例构造了一个初始化为文件系统对象temp的File对象。 然后在此File对象上调用mkdir()来创建一个名为temp的新目录。

关于File类我们将放在第二章中深入探讨。

1.1.2 通过RandomAccessFile访问文件内容

文件内容可以顺序或随机访问。 随机访问可以加快搜索和排序功能。 java.io.RandomAccessFile类的一个实例提供对文件的随机访问。 此功能在以下示例中进行了说明:

RandomAccessFile raf=new RandomAccessFile("employees.dat","r");
int empIndex=10;
raf.seek(empIndex*EMP_REC_LEN);
//读取员工记录的内容

在此示例中,文件employees.dat被放置了固定长度的员工记录,其中每条记录的字节长度为EMP_REC_LEN。以上正在查找的是索引为10(第一个记录位于索引0)的员工记录。该任务通过寻找(设置文件指针)到该记录的第一个字节的位置,该位置位于索引乘以记录长度,然后就可以访问到该记录了。

第3章探讨了RandomAccessFile类

1.1.3 通过流类流式传输数据

经典I/O包括用于执行I/O操作的流。字节流是有序的任意长度的字节序列。字节流从应用程序的输出流流出到目的地,并从源中的输入流流入到应用程序。图1-1说明了这些流程:


第一部分 Java I/O入门_第1张图片
20170831232321

Java在java.io包中提供了各种对目标地址写入的类;例如,字节数组和文件。Java还在该包中提供了用于标识从源中读入的类。示例中包含文件和线程管道。

例如,您将使用FileInputStream打开现有文件并将输入流连接到该文件。然后,您将调用各种read()方法通过输入流读取文件中的字节。 最后,你可以调用close()关闭流和文件。 请考虑以下示例 :

FileInputStream fis=null;
try{
  fis=new FileInputStream("image.jpg");
  //Read bytes from file
  int _byte;
  while((_byte=fis.read())!=-1){
    //Handle your logic
  }
}catch(IOException e){
  //Handle Exception
}finally{
  if (fis!=null) {
    try {
      fis.close();
    }
  }
}

此示例演示了打开文件并创建用于从文件读取字节的输入流的传统方式。然后就可以继续阅读文件的内容了。同时需要处理由java.io.IOException抛出的所有异常。
无论是否抛出异常,都必须关闭输入流和目标文件。这个动作放在finally语句块中进行。由于关闭资源的冗长性,您可以使用JDK 7中的try-with-resources语句自动关闭它,如下所示 :

try(FileInputStream fis=new FileInputStream("image.jpg")) {
  //Read bytes from file
  int _byte;
  while((_byte=fis.read())!=-1){
    //Handle your logic
  }
}catch (IOException e) {
  //Handle Exception
}

关于传统try-catch-finallytry-with-resources方法的区别我们将在后续章节中详细讲解。

一些流类用于过滤其他流类。例如,为了提高性能,BufferedInputStream从另一个流中读取字节块,再从缓冲区读取返回字节,直到缓冲区为空的时候,继续读取下一个字节块,如下示例所示:

try(FileInputStream fis=new FileInputStream("image.jpg");
BufferedInputStream bis=new BufferedInputStream(fis)) {
  //Read bytes from file
  int _byte;
  while((_byte=bis.read())!=-1){
    //Handle your logic
  }
}catch (IOException e) {
  //Handle Exception
}

创建从image.jpg文件读取的文件输入流。 该流被传递到缓冲的输入流构造器。 在缓冲的输入流上执行后续读取,在适当时调用文件输入流read()方法 。

第4章探讨流类

1.1.4 流类和标准I / O

许多操作系统支持标准I / O,它是在计算机程序及其环境开始执行时的预先连接的输入和输出数据流。 预先连接的流称为标准输入,标准输出和标准错误。

标准输入默认从键盘读取其输入。 此外,标准输出和标准错误默认将其输出写入屏幕。 然而,这些流可以被重定向以从不同的源读取输入并将输出写入到不同的目的地(例如文件)。

JDK 1.0通过将InputStream和PrintStream类型的in,out和err对象添加到java.lang.System类来引入对标准I / O的支持。 您可以在这些对象上指定方法调用来访问标准输入,标准输出和标准错误,如下所示:

int ch=System.in.read(); //从标准输入读取一个单个字符
System.out.println("Hello"); //使用标准输出写字符串
System.err.println("I/O error: "+ioe.getMessage()); //使用标准错误写字符串

除了探索InputStream和PrintStream,第4章也重新解读
标准I / O,让您了解如何以编程方式重定向这些流。

1.1.4.1 JDK 1.1和Writer/Reader类

JDK 1.0的I / O功能适用于流字节,但由于不考虑字符编码,因此无法正确流式传输字符。 JDK 1.1通过引入考虑到字符编码的writer / reader类来克服这个问题。 例如,java.io包中包含用于写入和读取字符流的FileWriter和FileReader类。
第5章中探讨各种Writer和Reader类


1.2 NIO

你可能感兴趣的:(第一部分 Java I/O入门)