1. 概念
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
2. 分类
1.按处理数据类型的不同,分为字节流和字符流
2.按数据流向的不同,分为输入流和输出流
3.按功能不同,分为节点流和处理流
节点流:直接操作数据源
处理流:对其他流进行处理
3. 抽象类定义
3.1 InputStream
InputStream的继承关系:蓝色为节点流,黑色为处理流(小红旗重点)
常用方法:
方法 | 描述 |
void close() | 关闭此输入流并释放与该流关联的所有系统资源 |
abstract int read() | 从输入流读取下一个数据字节 |
int read(byte[] b) | 从输入流中读取一定数量的字节并将其存储在缓冲区数组b中 |
int read(byte[] b, int off, int len) | 将输入流中最多len个数据字节读入字节数组 |
3.2 OutputStream
OutputStream的继承关系:蓝色为节点流,黑色为处理流(小红旗重点)
常用方法:
方法 | 描述 |
void close() | 关闭此输出流并释放与此流有关的所有系统资源 |
void flush() | 刷新此输出流并强制写出所有缓冲的输出字节 |
void write(byte[] b) | 将 b.length个字节从指定的字节数组写入此输出流 |
void write(byte[] b, int off, int len) | 将指定字节数组中从偏移量 off 开始的 len 个字节写入此输出流 |
abstract void write(int b) | 将指定的字节写入此输出流 |
3.3 Reader
Reader的继承关系:蓝色为节点流,黑色为处理流(小红旗重点)
常用方法:
方法 | 描述 |
abstract void close() | 关闭该流 |
int read() | 读取单个字符 |
int read(char[] cbuf) | 将字符读入数组 |
abstract int read(char[] cbuf, int off, int len) | 将字符读入数组的某一部分 |
3.4 Write
Writer的继承关系:蓝色为节点流,黑色为处理流(小红旗重点 )
常用方法:
方法 | 描述 |
void write(int c) | 写入单个字符 |
void write(char[] cbuf) | 写入字符数组 |
abstract void write(char[] cbuf, int off, int len) | 写入字符数组的某一部分 |
void write(String str) | 写入字符串 |
void write(String str, int off, int len) | 写入字符串的某一部分 |
Writer append(char c) | 将指定字符添加到此writer |
abstract void flush() | 刷新该流的缓冲 |
abstract void close() | 关闭此流,但要先刷新它 |
4. 文件流
分类 | 字节流 | 字符流 |
文件输入流 | FileInputStream | FileReader |
文件输出流 | FileOutputStream | FileWrite |
4.1 FilelnputStream
字节输入流
文件要读取,必须先找到这个文件
怎么找到:1.绝对定位 2.相对定位
绝对定位:以当前文件系统的根目录为基准
相对定位:以当前文件所在目录为标准
读取:默认一次读取一个字节,并且返回值是下一个字节的值,到达文件末尾,返回-1
read:方法重载,可以传入一个字节数组,把数据放到数组中,返回当前次,读取的字节个数,如果达到文件末尾,返回-1
【注意】:每次读取之后,数组不会清空,再读的时候,用读到的数据替换原来的数据。如果最后一次读了两个数据,就读完了,那么数组中还有一部分冗余数据
4.2 FileRader
字符输入流
一次读取一个字符,可以解决乱码问题,一般纯文本文件使用FileRader
像压缩包、视频等使用字节流,字符流会出现问题
4.3 FileOutPutStream
字节输出流
需要指定输出的文件路径,如果找不到该文件,会自动创建
write():写入
flush():刷缓存
构造方法:
FileOutputStream(String):传入文件地址,默认覆盖写入
FileOutputStream(String,boolean):boolean类型为true就追加写入,为false就覆盖写入
4.4 FileWrite
字符输出流
5. 缓冲流
分类 | 字节流 | 字符流 |
文件输入流 | BufferedInputStream | BufferedReader |
文件输出流 | BufferedOutputStream | BufferedWriter |
【特点】:
1.主要为了提高效率而存在的,减少物理读取次数
2.提供readLine()、newLine()这样便捷的方法(针对缓冲字符流)
3.在读取和写入的时候,会有缓存部分,调用flush为刷新缓存,将内存数据写入到磁盘
6. 转换流
输入流 | 输出流 |
InputStreamReader | OutputStreamWriter |
【特点】:
1.转换流是指将字节流向字符流的转换,主要有InputStreamReader和OutputStreamWrite
2.InputStreamReader主要是将字节流输入流转换成字符输入流
3.OutputStreamWrite主要是将字节流输出流转换成字符输出流
6.1 InputStreamReader
分类 | 方法 | 描述 |
构造方法 | InputStreamReader(InputStream in) | 创建一个使用默认字符集的该对象 |
常用方法 | void close() | 关闭该流并释放与之关联的所有资源 |
7. 打印流
【特点】:
1.打印流是输出最方便的类
2.包含字节打印流PrintStream、字符打印流PrintWrite
3.PrintStream是OutputStream的子类,把一个输出流的实例传递到打印流之后,可以更加方便输出内容,相当于输出流重新包装一下
4.PrintStream类的print()方法被重载很多次print(int i)、print( boolean b)、print( char c )
【标准输入/输出】:
Java的标准输入/输出分别通过System.in和System.out来代表,在默认的情况下分别代表键盘和显示器,当程序通过System.in来获得输入时,实际上是通过键盘获得输入。当程序通过System.out执行输出时,程序总是输出到屏幕。
在System类中提供了三个重定向标准输入/输出的方法 :
- static void setErr(PrintStream err) 重定向“标准”错误输出流
- static void setIn(InputStream in) 重定向“标准”输入流
- static void setOut(PrintStream out)重定向“标准”输出流
8. 数据流
1.为了方便的操作java语言的基本数据类型和String的数据,可以使用数据流
2.数据流有两个类:(用于读取和写出基本数据类型、String类的数据)
DataInputStream 和 DataOutputStream
分别“套接”在 InputStream 和 OutputStream 子类的流上
3.DataInputStream中的方法:
boolean readBoolean()
char readChar()
double readDouble()
long readLong()
String readUTF()
byte readByte()
float readFloat()
short readShort()
int readInt()
void readFully(byte[] b)
9. FIle类
9.1 File类特点
- java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关
- File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流。
- 想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对 象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录。
- File对象可以作为参数传递给流的构造器
9.2 File类构造方法
- public File(String pathname)以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。 绝对路径:是一个固定的路径,从盘符开始 相对路径:是相对于某个位置开始
- public File(String parent,String child)以parent为父路径,child为子路径创建File对象。
- public File(File parent,String child)根据一个父File对象和子文件路径创建File对象
9.3 使用
- 路径中的每级目录之间用一个路径分隔符隔开。
- 路径分隔符和系统有关: windows和DOS系统默认使用“\”来表示 UNIX和URL使用“/”来表示
- Java程序支持跨平台运行,因此路径分隔符要慎用。
- 为了解决这个隐患,File类提供了一个常量:public static final String separator。根据操作系统,动态的提供分隔符
举例:
File file1 = new File("d:\\shangyun\\info.txt"); File file2 = new File("d:" + File.separator + " shangyun " + File.separator + "info.txt"); File file3 = new File("d:/ shangyun "); |
9.4 FIle类常用方法
获取功能:
- public String getAbsolutePath():获取绝对路径
- public String getPath() :获取路径
- public String getName() :获取名称
- public String getParent():获取上层文件目录路径。若无,返回null
- public long length() :获取文件长度(即:字节数)。不能获取目录的长度。
- public long lastModified() :获取最后一次的修改时间,毫秒值
- public String[] list() :获取指定目录下的所有文件或者文件目录的名称数组
- public File[] listFiles() :获取指定目录下的所有文件或者文件目录的File数组
重命名功能:
- public boolean renameTo(File dest):把文件重命名为指定的文件路径
判断功能:
- public boolean isDirectory():判断是否是文件目录
- public boolean isFile() :判断是否是文件
- public boolean exists() :判断是否存在
- public boolean canRead() :判断是否可读
- public boolean canWrite() :判断是否可写
- public boolean isHidden() :判断是否隐藏
创建删除功能:
- public boolean createNewFile() :创建文件。若文件存在,则不创建,返回false
- public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。 如果此文件目录的上层目录不存在,也不创建。
- public boolean mkdirs() :创建文件目录。如果上层文件目录不存在,一并创建
注意事项:如果你创建文件或者文件目录没有写盘符路径,那么,默认在项目 路径下。
- public boolean delete():删除文件或者文件夹
删除注意事项:
Java中的删除不走回收站。
要删除一个文件目录,请注意该文件目录内不能包含文件或者文件目录
10. 对象流
10.1 定义
1.ObjectInputStream和OjbectOutputSteam
2.用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可 以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
3.序列化:用ObjectOutputStream类保存基本类型数据或对象的机制
4.反序列化:用ObjectInputStream类读取基本类型数据或对象的机制
5.ObjectOutputStream和ObjectInputStream不能序列化static和transient修
饰的成员变量
10.2 对象的序列化
1.对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从 而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传 输到另一个网络节点。//当其它程序获取了这种二进制流,就可以恢复成原 来的Java对象
2.序列化的好处在于可将任何实现了Serializable接口的对象转化为字节数据, 使其在保存和传输时可被还原
3.序列化是 RMI(Remote Method Invoke – 远程方法调用)过程的参数和返 回值都必须实现的机制,而 RMI 是 JavaEE 的基础。因此序列化机制是 JavaEE 平台的基础
4.如果需要让某个对象支持序列化机制,则必须让对象所属的类及其属性是可 序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一。 否则,会抛出NotSerializableException异常 Serializable Externalizable
5.凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:
1)private static final long serialVersionUID;
2)serialVersionUID用来表明类的不同版本间的兼容性。简言之,其目的是以序列化对象 进行版本控制,有关各版本反序列化时是否兼容。
3)如果类没有显示定义这个静态常量,它的值是Java运行时环境根据类的内部细节自 动生成的。若类的实例变量做了修改,serialVersionUID 可能发生变化。故建议, 显式声明。
4)简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验 证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的 serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同 就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异 常。(InvalidCastException)
10.3 使用对象流序列化对象
1.若某个类实现了 Serializable 接口,该类的对象就是可序列化的:
1)创建一个 ObjectOutputStream
2)调用 ObjectOutputStream 对象的 writeObject(对象) 方法输出可序列化对象
3)注意写出一次,操作flush()一次
2.反序列化
1)创建一个 ObjectInputStream
2)调用 readObject() 方法读取流中的对象
3.强调:如果某个类的属性不是基本数据类型或 String 类型,而是另一个 引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型的 Field 的类也不能序列化