传统 IO 流体系
理解节点流和处理流
直接以物理资源建立的流就是节点流,把节点流包装就是处理流。
InputStream 和 Reader
InputSteam 和 Reader 是所有输入流的抽象基类,它们的方法所有输入流都可以使用:
InputStream
- int read():从输入流中读取单个字节,返回所读取的字节数据。
- int read(byte[] b):从输入流中最多读取 b.length 个字节的数据,并将其存储在字节数组 b 中,返回实际读取的字节数。
- int read(byte[] b,int off,int len):从输入流中最多读取 len 个字节的数据,并将其存储在数组 b 中,当放入数组 b 中时从数组的 off 位置开始放入,返回实际读取的字节数。
Reader
- int read():从输入流中读取单个字符,返回所读取的字符数据。
- int read(char[] cbuf):从输入流中最多读取 cbuf.length 个字符的数据,并将其存储在字符数组 cbuf 中,返回实际读取的字符数。
- int read(char[] cbuf,int off,int len):从输入流中最多读取 len 个字符的数据,并将其存储在数组 cbuf 中,当放入数组 cbuf 中时从数组的 off 位置开始放入,返回实际读取的字符数。
除此之外,InputSteam 和 Reader 还支持以下方法来移动记录指针:
- void mark(int readAheadLimit):在记录指针当前位置进行一个标记 mark。
- boolean markSupported():判断此输入流是否支持 mark() 操作
- void reset():将此流的记录指针重新定位到上一次标记 mark 的位置
- long skip(logn n):记录指针向前移动 n 个字节/字符
OutputSteam 和 Writer
OutputStream 和 Writer 都提供如下方法:
- void write(int c):将指定的字节/字符输出到输出流中,其中 c 既可以代表字节,也可以代表字符。
- void writer(byte[]/char[] buf):将字节数组/字符数组中的数据输出到指定输出流中。
- void write(byte[]/char[] buf,int off,int len):将字节数组/字符数组中从 off 位置开始,长度为 len 的字节/字符输出到输出流中。
Writer还包含以下方法:
- void writer(String str):将 str 字符串里包含的字符输出到指定输出流中。
- void write(String str,int off,int len):将 str 字符串里从 off 位置开始,长度为 len 的字符输出到指定输出流中。
处理流的用法
上述4个基类用起来很繁琐,此时就有了处理流。使用处理流的思路是,使用处理流来包装节点流,程序通过处理流来执行输入/输出功能,让节点流与底层的 I/O 设备、文件交互。
实际识别处理流非常简单,只要流的构造器参数不是一个物理节点,而是已经存在的流,那么这种流就一定是处理流;而所有节点流都是直接以物理 IO 节点作为构造参数的。
输入/输出体系
4 个访问管道的流:PipeInputStream、PipeOutputStream、PipedReader、PipedWriter,用来实现进程之间通信功能。
4 个缓冲流:增加缓冲流之后需要使用 flush() 才可以将缓冲区的内容写入实际的物理节点。
对象流,主要用于实现对象的序列化。
转换流
输入/输出 体系中还提供了两个转换流,用于实现将字节流转换成字符流。分别是 InputStreamReader 和 OutputStreamWriter 。普通的 Reader 读取输入内容时不太方便,此时可以将普通的 Reader 再次包装成 BufferedReader ,利用 BufferedReader 的 readLine() 方法可以一次读取一行文本内容。
BufferReader 有一个 readLine() 方法可以一次读取一行内容,方便读取文本内容。
推回输入流
在输入/输出流体系中,有两个特殊的流与众不同,就是 PushbackInputStream 和 PushbackReader,它们都提供了如下方法:
- void unread(byte[]/char[] buf):将一个字节/字符数组内容推回到 推回缓冲区,从而允许重复读取刚刚读取的内容
- void unread(byte[]/char[] b,int off,int len):将一个字节/字符数组里从 off 开始,长度为 len 字节/字符的内容推回到 推回缓冲区,从而允许重复读取刚刚读取的内容
- void unread(int b):将一个字节/字符推回到 推缓冲区,从而允许重复读取刚刚读取的内容
重定向标准输入/输出
Java 的标准输入/输出分别通过 System.in 和 System.out 来实现,在默认情况下代表键盘和显示器。在 System 类里提供了如下三个重定向标准输入/输出的方法:
- static void setErr(PrintStream err):重定向 “标准” 错误输出流
- static void setIn(InputStream in):重定向 “标准” 输入流
- static void setOut(PrintStream out):重定向 “标准” 输出流
RandomAccessFile
RandomAccessFile 既可以读取文件内容,也可以向文件输出数据,与普通的输入流/输出流不同,RandomAccessFile 支持”随机访问”的方式,程序可以直接跳转到文件的任意地方来读写数据。
“随机访问” 翻译不确切,应该说是任意访问。
RandomAccessFile 有一个最大的局限,就是只能读写文件,不能读写其他 IO 节点。有如下两个方法来操作文件记录指针:
- long getFilePoint():返回文件记录指针的位置。
- void seek(long pos):将文件记录指针定位到 pos 位置。
RandomAccessFile 类有两个构造器,一个使用 String 参数来指定文件名,一个使用 File 参数来指定文件本身。另外,创建 RandomAccessFile 对象时还需要指定一个 mode 参数,该参数指定访问 RandomAccessFile 的访问模式。mode 参数有 4 个值:
- r:以只读模式打开指定文件。
- rw:以读、写方式打开指定文件,如果该文件尚不存在,则尝试创建该文件。
- rws:以读、写方式打开指定文件。该模式要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。
- rwd:以读、写方式打开文件。该模式要求文件内容的每个更新都同步写入到底层存储设备。
File 类
File 类是 java.io 包下与平台无关的文件和目录,不管是文件还是目录都是使用 File 类来操作。File 类能新建、删除、重命名文件和目录,但是不能访问文件内容本身(访问内容需要输入/输出流)。
访问文件和目录
File 类使用文件路径字符串来创建 File 实例,可以是绝对路径或者相对路径。以下是 File 类提供来操作文件和目录的方法:
- String getName():返回此 File 对象所表示的文件名或路径名。
- String getPath():返回此 File 对象所对应的路径名。
- File getAbsoluteFile():返回此 File 对象的绝对路径。
- String getParent():返回此 File 对象所对应目录的父目录名。
- boolean renameTo(File newName):重命名此 File 对象所对应的文件或目录。
- boolean exists():判断 File 对象所对应的文件或目录是否存在。
- boolean canWrite():判断 File 对象所对应的文件和目录是否可写。
- boolean canRead():判断 File 对象所对应的文件和目录是否可读。
- boolean isFile():判断 File 对象所对应的是否是文件,而不是目录。
- boolean isDirectory():判断 File 对象所对应的是否是目录,而不是文件。
- boolean isAbsolute():判断 File 对象所对应的文件或目录是否是绝对路径。
- long lastModified():返回文件的最后修改时间。
- long length():返回文件内容的长度。
- boolean createNewFile():当此 File 对象所对应的文件不存在时,该方法将新建一个该 File 对象所指定的新文件。
- boolean delete():删除 File 对象所对应的文件或路径。
- static File createTempFile(String prefix,String suffix):在默认的临时文件目录中创建一个临时的空文件。
- static File createTempFile(String prefix,String suffix,File directory):在 directory 所指定的目录中创建一个临时的空文件。
- void deleteOnExit():注册一个删除钩子,指定当Java虚拟机退出时,删除 File 对象所对应的文件和目录。
- boolean mkdir():试图创建一个 File 对象所对应的目录,必须对应一个路径,而不是一个文件。
- String[] list():列出 File 对象的所有子文件名和路径名,返回 String 数组。
- File[] listFile():列出 File 对象的所有子文件和路径,返回 File 数组。
- static File[] listRoots():列出系统所有的根路径。
注意:Windows的路径分隔符使用反斜线
(\)
,而Java程序中的反斜线表示转移字符,所有当需要在Windows的路径下包括反斜线,应该使用两条反斜线,或者直接使用斜线(/)
。
文件过滤器
File 类的 list() 方法中可以接受一个 FilenameFilter 参数,通过该参数可以只列出符合条件的文件。该 FilenameFilter 接口包含了一个 accept(File dir,String name) 方法,该方法将依次对指定 File 的所有子目录或文件进行迭代,如果该方法返回 true,则 list() 方法会列出该子目录或文件。
1 | File file = new File("D:/MyWork"); |