Java Io操作解析(1)

无简介

什么是IO

I/O输入/输出(Input/Output),分为IO设备和IO接口两个部分。 在POSIX兼容的系统上,例如Linux系统,I/O操作可以有多种方式,比如DIO(Direct I/O),AIO(Asynchronous I/O 异步I/O),Memory-Mapped I/O(内存映设I/O)等,不同的I/O方式有不同的实现 方式和性能,在不同的应用中可以按情况选择不同的I/O方式。

(以上来自百度百科

In computing, input/output or I/O (or, informally, io or IO) is the communication between an information processing system, such as a computer, and the outside world, possibly a human or another information processing system. Inputs are the signals or data received by the system and outputs are the signals or data sent from it. The term can also be used as part of an action; to “perform I/O” is to perform an input or output operation. I/O devices are used by a human (or other system) to communicate with a computer. For instance, a keyboard or mouse is an input device for a computer, while monitors and printers are output devices. Devices for communication between computers, such as modems and network cards, typically perform both input and output operations. 在计算机的运行中,input/output 或者简称I/O是在信息处理系统中的一种沟通方式,比如说一台电脑或者外部世界,又或者一个人、其他的信息处理系统。输入(Input)是这个系统接收到的信号或者数据,输出是这个信息处理系统向外界发送出来的信号或者数据。IO这个术语同样可以用于一个动作的一部分,运行 I/O可能是运行输入或者是输出操作。人们或者其他的系统使用I/O设备来和电脑进行交互。比如,键盘或者鼠标就是一种为电脑设计的输入设备,而显示器以及打印机就是输出的设备。比如说调制解调器以及网卡设备,就被用来和电脑进行交互,并同时兼有输入输出功能。 Note that the designation of a device as either input or output depends on perspective. Mice and keyboards take physical movements that the human user outputs and convert them into input signals that a computer can understand; the output from these devices is the computer’s input. Similarly, printers and monitors take signals that a computer outputs as input, and they convert these signals into a representation that human users can understand. From the human user’s perspective, the process of reading or seeing these representations is receiving input; this type of interaction between computers and humans is studied in the field of human–computer interaction. 要知道设备输入输出的定制在于到底持什么观点。人们用物理动作的方式使用鼠标和键盘来进行输出然后将它们转化为电脑的能理解的输入信号,这些设备输出的信息也就是电脑的输入。类似的,打印机和屏幕监视器获得电脑的输出信号来作为自己的输入信号,然后它们将这些信号进行转换并且以人们能以理解的样子呈现。以一个人类用户的观点来看,读或者看这些(输出或者陈述)就是在接受input,这种类型的人类和计算机之间的互动是一种在人机交互领域的研究。

(以上来自维基百科)

Java中的IO

“对语言设计人员来说,创建好的输入/输出系统是一项特别困难的任务。” ——《Think in Java》 无论是系统、还是语言的设计中IO的设计都是异常复杂的。面临的最大的挑战一般是如何覆盖所有可能的因素,我们不仅仅要考虑文件、控制台、网络、内存等不同的种类,而且要处理大量的不同的读取方式,如:顺序读取、随机读取,二进制读取、字符读取,按行读取、按字符读取…… Linux是第一个将设备抽象为文件的操作系统,在Linux中所有的外部设备都可以用读取文件的方法读取,这样编程人员就可以以操作文件的方法操作任何设备。C++在IO方面也做了一些改进――引进了流的概念,我们可以通过cin、cout读写一些对象。Java语言在IO设计方面取得较大的成功,它是完全面向对象的,主要采用装饰器模式避免大量的类,包括了最大的可能性,提供了较好的扩展机制…… Java库的设计者通过创建大量类来攻克这个难题。事实上,Java的IO系统采用了如此多的类,以致刚开始会产生不知从何处入手的感觉(具有讽刺意味的是,Java的IO设计初衷实际要求避免过多的类)。” 上面一段来自《Think in Java》,确实很多初学者刚刚学习java的IO时会比较茫然,不过等我们知道装饰器模式(Decorator)的用意、场景及其在Java的IO包中的使用,你可能会真正领会整个IO的FrameWork。 下面,将根据Thinking in Java中的讲解过程来继续研究。

1.File类

File类是java.io.File包下的一个类,从名字上来看,这个类是一个文件类,代指的是文件,然而事实上,这个类值得除了是一个文件之外,它还可能是一个文件夹。如果他是一个文件夹,那么我们可以通过File类下面的list方法获得这个文件夹下面的所有文件的名字:

private static void listFileNames(File file) {
String[] list = file.list();
for (int i = 0; i < list.length; i++) {
System.out.println(list[i]);
}
}

那么如果我只要取文件名中包含Test的文件,那么要怎么做? 第一种:我在上面已经获取到了所有的文件的名字,然后遍历获得的这些名字,如果名字中包含Test,那么我再把它输出出来。

private static void listFileNames(File file) {
String[] list = file.list();
for (int i = 0; i < list.length; i++) {
String name = list[i];
if (name.contains(“Test”)) {
System.out.println(name);
}
}
}

第二种:java的工程师在设计的时候就帮我们在这些程序猿想到了,他们设计了一种方法,这就是list的一个重载方法list(FilenameFilter filter)。 下面是list(FilenameFilter filter)的代码

public String[] list(FilenameFilter filter) {
String names[] = list();
if ((names == null) (filter == null)) {
return names;
}
//上面的代码会将目录下的文件或者目录都列出来,如果过滤项目是空,就将文件名的数组直接返回
List v = new ArrayList<>();
for (int i = 0 ; i < names.length ; i++) {
//看到这里,就有了疑问,这个filter的accept方法在哪里? 现在,跳过这里,看【后面的代码
if (filter.accept(this, names[i])) {

        //看到这里,就发现,如果返回值是true的话,这个名字才会被加入给我们的结果中,也就是说如果这个结果是我们需要的,那么就返回true,然后我们就能在最后的返回结果哪里获得它了,也就实现了【[我们自己写的方法](https://sumile.cn/archives/994.html#3)】的那样的结果,【[返回,继续查看](https://sumile.cn/archives/994.html#4)】
            v.add(names\[i\]);
        }
    }
    return v.toArray(new String\[v.size()\]);

}

这里是FilenameFilter中的代码:

interface FilenameFilter {
/**
* Tests if a specified file should be included in a file list.
*
* @param dir the directory in which the file was found.
* @param name the name of the file.
* @return true if and only if the name should be
* included in the file list; false otherwise.
*/
boolean accept(File dir, String name);
}

这是一个接口,从注释中我们看到,第一个参数查询的文件夹的路径,第二个是文件的路径,如果我们调用的是list(FilenameFilter fileFilter)方法,并传入了fileFilter方法,那么我们就必须覆盖父类的方法,如下:

String[] listFilters = file.list(new FilenameFilter() {

@Override
public boolean accept(File dir, String name) {
return false;
}
});

在accept方法中,我们就可以对获得的名字进行预处理了,比如我们要做的“判断名字中是否有Test”

String[] listFilters = file.list(new FilenameFilter() {

@Override
public boolean accept(File dir, String name) {
if (name.contains(“Test”)) {
return true;
}
return false;
}
});

在accept中,我们什么时候返回true,什么时候返回false呢?点【这里】我们去看这个返回的值是怎么被使用的。

File类部分方法使用

File file = new File(“src\\cn\\sumile\\2.txt”);
fileData(file);
System.out.println();
File file2 = new File(“src\\cn\\sumile”);
fileData(file2);
System.out.println();
File file3 = new File(“src\\cn\\sumile\\MainClass2.java”);
// 是否是可执行
System.out.println(file.canExecute());
// 对比两个文件(对比的是路径)
System.out.println(file2.compareTo(file3));
try {
// 创建文件
System.out.println(file3.createNewFile());
} catch (IOException e) {
e.printStackTrace();
}
// 删除文件
// System.out.println(“文件” + file3.getAbsolutePath() + “删除:” +
// file3.delete());
// 磁盘剩余空间
System.out.println(“磁盘剩余空间:” + file.getFreeSpace() / 1024 / 1024 / 1024 + “G”);
System.out.println(“磁盘总空间:” + file.getTotalSpace() / 1024 / 1024 / 1024 + “G”);
System.out.println(“磁盘可用空间:” + file.getUsableSpace() / 1024 / 1024 / 1024 + “G”);
System.out.println(“文件修改名称:” + file.renameTo(new File(“src\\cn\\sumile\\1.txt”)));

API参考

2.输入和输出

首先来看一下在《Thinking in Java》书中对InputStream类型的介绍:

功能

构造器参数

如何使用

ByteArrayInputStream

允许将内存的缓冲区当做InputStream来使用

缓冲区,字节将从中取出作为一种数据源:将其与FilterInputStream对象相连以提供有用的接口

StringBufferInputStream

将String转换成InputStream

字符串。底层实现实际使用StringBuffer作为一种数据源:将其与FilterInputStream对象相连以提供有用的接口

FileInputStream

用于从文件中读取信息

字符串。表示文件名、文件或FileDescriptor对象作为一种数据源:将其与FilterInputStream对象相连以提供有用的接口

PipedInputStream

产生用于写入相关Pipedoutput Stream的数据。实现“管道化”的概念

PipedOutputStream作为多线程中:将其与FilterInputStream对象相连以提供有用的接口

SequenceInputStream

将两个或多个InputStream对象转换成单一的InputStream

两个InputStream对象或一个容纳InputStream对象的容器Enumeration作为一种数据源:将其与FilterInputStream对象相连以提供有用的接口

FilterInputStream

抽象类,作为“装饰器”的忌口。其中“装饰器”为其他的InputStream类提供有用的功能。

功能

构造器参数

如何使用

ByteArrayOutputStream

在内存中穿件缓冲区,所有送往“流”的数据都要防止在此缓冲区

缓冲区初始化尺寸(可选的)用于指定数据的目的地,将其与FilterOutputStrem对象相连以提供有用的接口

FileOutputStream

用于将信息写至文件

字符串,表示文件名、文件或FileDescriptor对象指定数据的目的地,将其与FilterOutputStream对象相连以提供有用的接口

PipedOutputStream

任何写入其中的信息都会自动作为相关PipedInputStream 的输出。实现“管道化”的概念

PipedInputStream指定用于多线程的数据的目的地,将其与FilterOutputStream对象相连以提供有用接口

FilterOutputStream

抽象类,作为”装饰器”的接口。其中,“装饰器”为其他OutputStream提供有用功能

-------------本文结束  感谢您的阅读-------------
下次一定