IO流

胡泽宇 2020年02月24日 45次浏览

文件IO

将数据保存到文件等其他物理设备上,保证数据可以在断电之后持久保存。

File类

代表了文件或目录。它只能操作(创建、删除、重命名)文件或目录本身,不能读取文件的内容。

  • 绝对路径:以根路径(盘符)开头的路径就是绝对路径。
  • 相对路径:不是绝对路径,就是相对路径。

File的基本用法

  1. 创建File对象。
  2. 调用方法 不同大方法需要参考API文档。
    • 调用方法时,要什么参数就给什么参数。
常用的方法:
static listRoots()  列出磁盘的所有根路径(盘符)。
String[] list()  列出当前目录下所有文件和子目录。

实例:
从某个目录开始,一依次把所有文件都访问一遍。

IO流

input、output各种物理节点内的数据。
流的分类
  • 按方向分(从运行程序所在内存来看,如果数据是从程序自身流出,用输出流.如果数据是流入程序自身,用输入流):
    • 输入流: 用于读取数据。
    • 输出流: 用于写出数据。
  • 按数据单元分
    • 字节流(以Stream结尾): 每次读、写一个字节(Byte),Byte就是计算机管理数据的最小单元。因此字节流可以读/写任意的文件。
    • 字符流(以Reader、Writer结尾): 每次读、写一个字符。可以非常方便读/写文本文件。
  • 按角色来分
    • 节点流: 直接关联代表数据源的IO节点(必须直接与物理节点关联)。
    • 处理流(过滤流、包装流): 建立在其他流的基础之上,用于对。
抽象基类
  • InputStream
  • OutputStream
  • Reader
  • Writer

Java 输入/输出流体系中常用的流分类

分类字节输入流字节输出流字符输入流字符输出流
抽象基类InputStreamOutputStreamReaderWriter
文件FileInputStreamFileOutputStreamFileReaderFileWriter
数组ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter
字符串 StringReaderStringWriter
以上都是节点流以下都是处理流(包装流、过滤流)
抽象基类FilterInputStreamFilterOutputStreamFilterReaderFilterWriter
缓冲BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter
打印 PrintStream PrintWriter
转换 InputStreamReaderOutputStreamWriter
特殊流DataInputStreamDataOutputStream
对象流ObjectInputStreamObjectOutputStream

输入流的最基本的方法

只要创建输入流,就相当于得到一根有水的水管(抽象理解)。

  • 字节流,每个水滴就是一个字节
  • 字符流,每个水滴就是一个字符
int read()   读取一滴水
int read(xxx[] buffer)   读取N滴水到数组中,返回实际读取的水滴数
int read(char[] buffer,int off,int length) 读取N滴水、保存数组的中间部分中。

输出流的最基本的方法

只要创建输出流,就相当于得到了一根空的水管(要往里面加水滴)

void write(int)  输出一滴水
void write(xxx[] buffer)  输出数组所有的水滴
void write(xxx[] buffer,int off,int length)  输出数组中的中间一段
利用InputStream和OutputStream(字节流)实现文件拷贝

1

利用Reader和Writer(字符流)实现文件拷贝

2


字节流与字符流的区别

  • 字节流的功能更强大,可以读写所有文件。
  • 字符流在读写文本更加的方便。

包装流和节点流的关系

3

缓冲流

因为内存速度 > 外设(磁盘、网络)速度
如果让内存输出一个数据单元,然后外设处理一个数据单元。
必须要等外设处理好数据单元之后,内存才会再输出下一个单元。 
肯定会造成程序性能的浪费。

缓冲流:内存先把所有数据输出到缓冲中, 在缓冲中的数据再交给外设去慢慢处理。释放的内存就可以继续处理下一个程序。

当使用缓冲流时,必须要使用 flush()方法将数据"冲"到底层物理设备中。(程序突然退出时,有可能数据还未输出物理设备)
如果正常调用close()方法关闭流,程序会包装先执行flush() 就有close()就行了。

利用BufferedReader读取abc.txt

4

打印流

利用PrintStream打印输出到文件

5

一般来说输入用BufferedReader合适 输出用PrintStream合适

转换流

传入一个字节流就会返回一个字符流

负责将字节流转换成字符流。
很多情况下,程序拿到的只是字节流。但实际上知道它是字符流。
此时,就可以把字节流转换成字符流
System.in  就是InputStream  但是键盘上的肯定都是字符 就可以转成字符流

利用InputStreamReader把字节流转换为字符流

6

特殊流

DataInputStream提供了一系列readXxx() 专门用于读取不同类型的数据。
DataOutputStream提供了一系列writeXxx(Xxx 数据) 专门用于写入不同类型的数据。

DataInputStream和DataOutputStream是用java内部格式来记录的,因此DataOutputStream输出的内容,应该使用DataInputStream读取
7

重定向标准输入、输出

标准输出,就是电脑的屏幕。
System.setOut即可换掉标准输出

标准输入,代表电脑的键盘。
System.setIn即可换掉标准输入

8

9

更改了System的标准输入输出,实现了文件拷贝
10

读写其他进程的数据

Runtime的exec()可用于平台命令的方法,运行之后就会返回一个Process对象。

Process对象有如下的方法:
getInputStream()  获取进程的输入流(程序从进程中读数据)
getErrorStream() 获取进程的错误输入流(程序从进程读数据)
getOutputStream() 获取进程的输出流(程序向进程写数据)

RandomAccessFile

RandomAccess: 任意访问,想访问哪里就访问哪里。
File: 只能(读、写)文件

前面介绍的输出流,不能向文件中追加内容,但RandomAccessFile可以。

该类的构造器:
RandomAccessFile(String 文件名,String mode)

mode参数作用如下:
r : 只读
rw : 读写
rws : 读写。对文件内容和元数据(meta data)所做的修改要同步写入底层存储设备。
rwd : 读写。值要求对文件内容所做的修改要同步写入底层存储设备。

实例读取文件:
11
默认情况下,RandomAccessFile总是从第一个字节开始读、写
读写位置:
12
seek(long pos) 移动到指定位置开始读、写
利用RandomAccessFile往文件中追加内容:
13
14

RandomAccessFile通常可用于实现多线程、断点下载工具(迅雷)。