IO流
File类的作用
- java.io.File类:文件和目录路径名的抽象表示形式,与平台无关
- File 能新建,删除,重命名文件和目录,但File不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流
- File 类只能操作文件本身,但是不能操作文件内容,类似于,你可以把一个日记本放在各种地方,但是不能在日记本中写日记
访问文件名
文件检测
文件相关操作
判断并增加文件
删除文件
目录相关操作
- FIle指的是计算机操作系统中的文件及文件夹
- File 对象可以作为参数传递给流的构造函数
- FIle类常见构造方法:
- public File(String pathname)
- 以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性 user.dir中存储
- public FIle(String parent,String child)
- 以parent 为父路径,child 为子路径创建File对象。
- public File(String pathname)
- File的静态属性 String separator 存储了当前系统的路径分隔符。在UNIX中,此字段为 ‘/’ ,在Windows中,为‘\’
练习题
- 遍历d盘下的JAVA(STUDY)文件夹,把test文件夹下所有的目录与文件全部遍历出来,直到全部遍历完成,无论层级有多深,要全部遍出来
Java IO原理
- IO 流用来处理设备之间的数据传输
- Java程序中,对于数据的输入/输出操作以“流(stream)"的方式进行
- java.io 包提供了各种”流“类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据
- 输入input :读取外部数据(磁盘,光盘等存储设备的数据)到程序(内存)中
- 输出output:将程序(内存)数据输出到磁盘,光盘等存储设备中
- 无论是输入还是输出,都是指的计算机的操作
流的分类
- 通过程序把一个图片放到一个文件夹中:先把图片转化为一个数据集(例如二进制),把这些数据一点点的传到文件夹中,这个传递的过程就类似于水的流动,我们就可以称这个整体的数据集是一个数据流。
按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
按数据流的流向不同分为:输入流,输出流
按流的角色不同分为:节点流,处理流
Java的IO流供涉及40多个类,实际上非常规则,都是从如下4个抽象基类派生的。由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。
IO流体系
文件流(数据流的读写都是基于文件的操作)
- FileInputStream
- FileOutputStream
- FileReader
- FileWriter
- 以上这些都是计算机与硬盘/硬盘之间发生的IO操作,基于硬盘的读写相对是比较慢,这个操作的速度受到硬盘的读写速度的制约
文件字节输入流(FileInputStream)
下面是优化版本
文件字节输出流(FileOutputStream )
练习题
- 编写一个程序,把一个文件复制到指定文件夹下
优化
复制其他类型文件也可以,如图片
注意:文件字节流非常通用,可以用来操作字符文档,还可以操作任何的其他类型文件,图片,压缩包……,因为字节流直接使用的是二进制
文件字符输入流(FileReader )
读取文件操作步骤:
- 建立一个流对象,将已存在的一个文件加载进流
FIleReader fr = new FileReader("Test.txt");
- 创建一个临时存放数据的数组
char[] ch=new char[1024]
- 调用流对象的读取方法将流中的数据读入到数组中
fr.read(ch);
文件字符输出流(FileWriter)
练习题
- 编写一个程序,把一个文件复制到指定文件夹下
注意:
- 定义文件路径时,注意:可以用 “/”或者“\"
- 在写入一个文件时,如果目录下有同名文件将被覆盖
- 在读取文件时,必须保证该文件已存在,否则出异常
处理流之一:缓冲流
缓冲流(数据流的读写都是基于内存的操作)
- 缓冲流就是先将数据缓冲到内存中,在内存种去做 Io 操作,基于内存的 io 操作大概比基于硬盘的 io 操作快7500多倍
- 为了提高数据读写的速度,Java API 提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组
- 根据数据操作单位可以把缓冲流分为:
- BufferedInputStream 和 BufferedOutputStream —》FileInputStream 和 FIleOutputStream
- BufferedReader 和 BufferedWriter ---------------------》FIleReader 和 FileWriter
- 缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法。
- 对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush()将会使内存中的数据立刻写出
- 注意:缓冲流是把数据缓冲到内存中
BufferedInputStream
BufferedOutputStream
copyFile
BufferedReader
BufferedWriter
copyFile
处理流之二:转换流
- 转换流提供了在字节流和字符流之间的转换
- java API 提供了两个转换流:
- InputStreamReader 和 OutputStreamWriter
- 字节流中的数据都是字符时,转成字符流操作更高效
InputStreamReader
OutPutStreamWriter
main
处理流之三: 标准输入/输出流
- System.in 和 System.out 分别代表了系统标准的输入和输出设备
- 默认输入设备是键盘,输出设备是显示器
- System.in 的类型是 inputStream
- System.out 的类型是 PrintStream , 其是 OutputStream 的子类 FilterOutputStream 的子类
练习
-
把控制台输入的内容写到指定的TXT 文件中 ,接收到字符串 over ,就结束程序的运行
-
在一个TXT文件中,写一组用户名和密码,通过控制台输入用户名和密码,与TXT文件中的用户名和密码做对比,如果一样就打印登陆成功,如果不一致就打印用户名,密码错误
处理流之四:打印流(了解)
- 在整个IO包中,打印流是输出信息最方便的类
- PrintStream (字节打印流)和 PrintWriter (字符打印流)提供了一系列重载的 print 和 println 方法,用于多种数据类型的输出
- printStream 和 PrintWriter 的输出不会抛出异常
- PrintStream 和 PrintWriter 有自动 flush 功能
- System.out 返回的是 PrintStream 的实例
处理流之五:数据流(了解)
- 为了方便地操作 Java语言的基本数据类型的数据,可以使用数据流
- 数据流有两个类(用于读取和写出数据类型的数据)
- DataInputStream 和 DataOutputStream 分别 “套接” 在 InputStream 和OutputStream 节点流上
- DataInputStream 中的方法:
boolean(readBoolean()) | byte readByte() |
---|---|
char readChar() | float readFloat() |
double readDouble() | short readShort() |
long readLong() | int readInt() |
String readUTF() | void readFully(byte[] b) |
- DataOutputStream中的方法(将上面的read 改为 write即可)
处理流之流: 对象流(将一个对象转化为一个数据流,然后进行读写)——涉及序列化,反序列化
例如:Person对象
1.把这个对象存到电脑的硬盘上
- 硬盘的基础是二进制,那就需要把对象转化位一个二进制的字节流,把这个流保存到电脑上。要使用这个对象的时候,要把这个流转化为对象再使用。
2.把这个对象通过网络传到另一个机器上,网络的通信基础是二进制,也就是需要将一个对象转换为二进制的数据流,然后把这个流通过网络进行传输,在网络传输的另一端,接收者如果要使用接收的对象,得先把对象的流转化为对象才行
正是因为保存对象到硬盘(对象的持久化)和对象的网络传输,需要做这两件事,就产生了一个对象的输入与输出流
ObjectinputStream / ObjectOutputStream
- 永于存储和读取对象的处理流,它的强大之处就是可以把 Java 中的对象写入到数据源中,也能把对象从数据源中还原回来
- 序列化(Serialize):用 ObjectOutputStream 类将一个 Java 对象写入到 IO 流中
- 反序列化(Deserialize):用 ObjectInputStream 类从 IO 流中恢复该 Java 对象
- 他们都针对的是对象的各种属性,不包括类的属性(类成员变量和类成员方法,即 static 类型)
- ObjectinputStream 和 ObjectOutputStream 不能序列化 static 和 transient 修饰的成员变量
对象的序列化
- 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
- 序列化的好处在于可将任何实现了 Serializable 接口的对象转化为字节数据,使其在保存和传输时可被还原
- 序列化是 RMI (Remote Method Invoke – 远程方法调用)过程的参数和返回值都必须实现的机制,而 RMI 是 JAVAEE 的基础。因此序列化机制是 JavaEE平台的基础
- 如果需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
- Serializable
- Externalizable
- 凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量 :serialVersionUID
- serialVersionUID 是用来表明类的不同版本间的兼容性
- 如果类中没有显示定义这个静态变量,它的值是java运行时环境根据类的内部细节自动生成的。若类的源代码作了修改,serialVersionUID 可能发生变化。故建议:显式声明
- 希望类的不同版本对序列化兼容,因此需确保类的不同版本具有相同的 serialVersionUID
- 不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID
- serialVersionUID 是用来表明类的不同版本间的兼容性
使用对象流序列化对象
-
若某个类实现了 Serializable 接口,该类的对象就是可序列化的:
- 创建一个 ObjectOutputStream
- 调用 ObjectOutputStream 对象的 writeObject(对象) 方法输出可序列化对象。注意写出一次,操作 flush()
-
反序列化:
- 创建一个 ObjectInputStream
- 调用 readObject() 方法读取流中的对象
- 强调:如果某个类的字段不是基本数据类型或 String 类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类的 Field 的类也不能序列化
随机存取文件流—RandomAccessFile类
- RandomAccessFile 类支持 ”随机访问“ 的方式,程序可以直接跳到文件的任意地方来读,写文件
- 支持只访问文件的部分内容
- 可以向已存在的文件后追加内容
(随机:例如一个TXT文件,其中有100行数据,可以直接读取第50行的数据,也可以在第89行插入数据。这个才是随机的概念)
-
RandomAccessFile 类对象可以自由移动记录指针:
- long getFIlePoint(): 获取文件记录指针的当前位置
- void seek(long pos): 将文件记录指针定位到 pos 位置
-
构造器:
- public RandomAccessFile(File file,String mode)
- public RandomAccessFile(String name,String mode)
-
创建 RandomAccessFIle 类实例需要指定一个 mode 参数,该参数指定 RandomAccessFile 的访问模式:
- r : 以只读方式打开
- rw : 打开以便读取和写入
- rwd :打开以便读取和写入;同步文件内容的更新
- rws :打开以便读取和写入;同步文件内容和元数据的更新
- 最常用的是 r 和 rw
注意,如果是在文件的开头或者中间的某个位置开始写的话,就会把写的内容覆盖掉等长度的内容
流的基本应用小结
-
流是用来处理数据的
-
处理数据时,一定要先明确数据源,与数据目的地
- 数据源可以是文件,可以是键盘
- 数据目的地可以是文件,显示器或者其他设备
-
而流只是帮助数据进行传输,并对传输的数据进行处理,比如过滤处理,转换处理等。
-
字节流 – 缓冲流(重点)
- 输入流 InputStream – FileInputStream – BufferedInputStream
- 输出流 OutputStream – FileOutputStream – BufferedOutputStream
-
字符流 – 缓冲流(重点)
- 输入流 Reader – FileReader – BufferedReader
- 输出流 Writer – FileWriter – BufferedWriter
-
转换流
- InputStreamReader 和 OutputStreamWriter
-
对象流 ObjectInputStream 和 ObjectOutputStream (难点)
- 序列化
- 反序列化
-
随机存取流 RandomAccessFIle(掌握读取,写入)