IO
javascript:;
- 可以将数据从本地文件读取出来
- 可以将数据从内存保存到本地文件
概述(参照物是内存)
- I表示input,是数据从硬盘进内存的过程,称之为读。
- O表示output,是数据从内存到硬盘的过程,称之为写。
- IO的数据传输,可以看作是一种数据的流动,按照流动的方向,以内存为参照物,进行读写操作
IO流的分类
按流向分
按数据类型分
- 字节流:操作所有类型的文件,包括音频视频图片等
- 字符流:只能操作纯文本文件,包括Java文件,txt文件等
注:
- 纯文本文件:用记事本打开能读的懂,那么这样的文件就是纯文本文件
- 如果想要拷贝,一律使用字节流或者字节缓冲流
- 想要把文本文件中的数据读到内存中,请使用字符输入流
- 想要把内存中的数据写道文本文件中,请使用字符输出流
- GBK码表中一个中文2个字节,UTF-8编码格式一个中文3个字节
- 字节流
1.1 输出流 FileOutputStream
构造方法
FileOutputStream(File file) 创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(File file, boolean append) 创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(FileDescriptor fdObj) 创建文件输出流以写入指定的文件描述符,表示与文件系统中实际文件的现有连接。
FileOutputStream(String name) 创建文件输出流以指定的名称写入文件。
FileOutputStream(String name, boolean append) 创建文件输出流以指定的名称写入文件。
注意事项
- 如果文件不存在,它会帮我们自动创建出来
- 如果文件存在,会把文件清空
常用方法
- public void write(int b):将指定的字节写入此文件输出流。
注:传递一个整数时,那么实际上写入文件中的,是这个整数在码表中对应的那个字符
- public void close():关闭此文件输出流并释放与此流相关联的任何系统资源。
注:每次使用完流必须要释放资源
写入数据的三种方式
- public void write(int b):一次写入一个字节
- public void write(byte[] b):一次写一个字节数组数据
- public void write(byte[] b,int off ,int len):一次写一个字节数组的部分数据。len是表示几个
字节流实现换行和追加
- 写完数据和,加换行符。windows:\r\n,linux:\n,mac:\r
追加
- FileOutputStream(String name, boolean append) 创建文件输出流以指定的名称写入文件。
FileOutputStream fos = new FileOutputStream("D:\FileTest\b.txt",true);
- FileOutputStream(File file, boolean append) 创建文件输出流以写入由指定的 File对象表示的文件。
这俩个构造方法的第二个参数表示是否续写,如果为true则继续添加不删除原先文件的内容
提高拷贝速度的方法
字节流通过创建字节数组,可以一次读写多个数据。
- public int read(byte[] b):从输入流读取最多b.length个字节数据
返回的是读入缓冲区的总字节数,也就是实际读取字节个数
1.2字节输入流FileInputStream
1.3 缓冲流
缓冲流是为了提供效率的,不能直接操作文件,需要传递字节流
字节缓存流BufferOutputStream
- BufferOutputStream:字节缓冲输出流
- BufferedInputStream:字节缓存输入流
构造方法:
- 字节缓冲输出流:BufferedOutPutStream(OutputStream out)
- 字节缓冲输入流:BufferedInputStream(InputStream in)
字节缓冲流仅仅是提供缓冲区,而真正的读写数据还得以考基本的字节流对象进行操作
- 字符流
由于字节流操作中文不是特别的方便,所以Java就提供字符流
字节流读取文件,读到内存中,有可能出现乱码,导致写入的时候也可能出现乱码
概述
- 字符流 = 字节流 + 编码表
- 不管在什么表中,中文的第一个字节一定是负数
注意事项
- WIndows默认使用码表为:GBK,一个中文字符2个字节
- idea和以后工作默认使用Unicaode的UTF-8编码格式,一个中文3个字符
编码
- byte[] getBytes():使用平台默认字符集将改String编码为一系列字节,将结构存储到新的字节数组中
- byte[] getBytes(String charsetName):使用指定的字符集将改String编码为一系列字节,将结构存储到新的字节数组中
解码
- String(byte[] bytes):通过使用平台默认字符集解码指定的字节数组来构造新的String
- String(byte[] bytes,String charsetName):通过指定的字符集解码指定的字节数组来构造新的String
1.1 输出流 FileWriter
构造方法
FileWriter(File file) 给一个File对象构造一个FileWriter对象。
FileWriter(File file, boolean append) 给一个File对象构造一个FileWriter对象。
FileWriter(FileDescriptor fd) 构造与文件描述符关联的FileWriter对象。
FileWriter(String fileName) 构造一个给定文件名的FileWriter对象。
FileWriter(String fileName, boolean append) 构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。
常用方法
void write(int c)写一个字符
void write(char[] cbuf)写出一个字符数组
void write(char[ cbuf, int off, int len)写出字符数组的一部分
void write(String str)写一个字符串
void write(String str, int off, int len)写一个字符串的一部分
注意事项
- 如果文件不存在,就创建。但是要保证父级路径存储。
- 如果文件存在就清空
- 写出int类型的整数,实际写出的是整数在码表上对应的字符。
- 写出字符串数据,是吧字符串本身原样写出。
- 每次使用完流必须要释放资源。
特殊方法
- flush():刷新流,还可以继续写数据
- close():关闭流,释放资源。但是在关闭之前会先刷新流。一旦关闭,就不能在写数据
1.2 输入流FileReader
构造方法
FileReader(File file)新的 FileReader ,给出 File读取。
FileReader(FileDescriptor fd)一个新的 FileReader ,给定 FileDescriptor读取。
FileReader(String fileName)一个新的 FileReader ,给定要读取的文件的名称。
1.3字符缓冲流
- BufferedWriter:可以将数据高效的写出
- BufferedReader:可以将数据高效的读取到内存
特有功能
BufferedWriter字符缓冲输出流
- void newLine():写一行行分隔符,行分隔符字符串由系统属性定义
BufferedReader字符缓冲输入流
- public String readLine():读一行文件。结构包括行的内容的字符串,不包括任何终止字符串,如果流的结尾已经到达,则返回null
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("day11\a.txt"));
String line;
while ((line=br.readLine())!=null){
System.out.println(line);
}
br.close();
}
}
3.转换流
3.1字符流中和编码解码问题相关的两个类【理解】
- InputStreamReader:是从字节流到字符流的桥梁,父类是Reader
它读取字节,并使用指定的编码将其解码为字符
它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集
- OutputStreamWriter:是从字符流到字节流的桥梁,父类是Writer
是从字符流到字节流的桥梁,使用指定的编码将写入的字符编码为字节
它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集
3.2转换流读写数据【应用】
- 构造方法
方法名 说明
InputStreamReader(InputStream in) 使用默认字符编码创建InputStreamReader对象
InputStreamReader(InputStream in,String chatset) 使用指定的字符编码创建InputStreamReader对象
OutputStreamWriter(OutputStream out) 使用默认字符编码创建OutputStreamWriter对象
OutputStreamWriter(OutputStream out,String charset) 使用指定的字符编码创建OutputStreamWriter对象
-
代码演示
public class ConversionStreamDemo {
public static void main(String[] args) throws IOException {
//OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myCharStream\osw.txt"));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myCharStream\osw.txt"),"GBK");
osw.write("中国");
osw.close();
//InputStreamReader isr = new InputStreamReader(new FileInputStream("myCharStream\\osw.txt"));
InputStreamReader isr = new InputStreamReader(new FileInputStream("myCharStream\\osw.txt"),"GBK");
//一次读取一个字符数据
int ch;
while ((ch=isr.read())!=-1) {
System.out.print((char)ch);
}
isr.close();
}
}
4.对象操作流
使用一个字节序列表示一个对象
4.1对象序列化流【应用】
- 对象序列化介绍
- 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象
- 这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息
- 字节序列写到文件之后,相当于文件中持久保存了一个对象的信息
- 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
- 对象序列化流: ObjectOutputStream
- 将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象
- 构造方法
方法名 说明
ObjectOutputStream(OutputStream out) 创建一个写入指定的OutputStream的ObjectOutputStream
- 序列化对象的方法
方法名 说明
void writeObject(Object obj) 将指定的对象写入ObjectOutputStream
-
示例代码
学生类
public class Student implements Serializable {
private String name;
private int age;
......
}
测试类
public class ObjectOutputStreamDemo {
public static void main(String[] args) throws IOException {
//ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myOtherStream\oos.txt"));
//创建对象
Student s = new Student("佟丽娅",30);
//void writeObject(Object obj):将指定的对象写入ObjectOutputStream
oos.writeObject(s);
//释放资源
oos.close();
}
}
- 注意事项
- 一个对象要想被序列化,该对象所属的类必须必须实现Serializable 接口
- Serializable是一个标记接口,实现该接口,不需要重写任何方法
3.2对象反序列化流【应用】
- 对象反序列化流: ObjectInputStream
- ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象
- 构造方法
方法名 说明
ObjectInputStream(InputStream in) 创建从指定的InputStream读取的ObjectInputStream
- 反序列化对象的方法
方法名 说明
Object readObject() 从ObjectInputStream读取一个对象
-
示例代码
public class ObjectInputStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myOtherStream\oos.txt"));
//Object readObject():从ObjectInputStream读取一个对象
Object obj = ois.readObject();
Student s = (Student) obj;
System.out.println(s.getName() + "," + s.getAge());
ois.close();
}
}
3.3serialVersionUID&transient【应用】
- serialVersionUID
- 用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?
- 会出问题,会抛出InvalidClassException异常
- 如果出问题了,如何解决呢?
- 重新序列化
- 给对象所属的类加一个serialVersionUID
- private static final long serialVersionUID = 42L;
- transient
- 如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
- 给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
-
示例代码
学生类
public class Student implements Serializable {
private static final long serialVersionUID = 42L;
private String name;
// private int age;
private transient int age;
......
}
测试类
public class ObjectStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// write();
read();
}
//反序列化
private static void read() throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myOtherStream\\oos.txt"));
Object obj = ois.readObject();
Student s = (Student) obj;
System.out.println(s.getName() + "," + s.getAge());
ois.close();
}
//序列化
private static void write() throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myOtherStream\\oos.txt"));
Student s = new Student("佟丽娅", 30);
oos.writeObject(s);
oos.close();
}
}
5.Properties集合(混眼熟)
5.1Properties作为Map集合的使用【应用】
- Properties介绍
- 是一个Map体系的集合类
- Properties可以保存到流中或从流中加载
- 属性列表中的每个键及其对应的值都是一个字符串
5.2Properties作为Map集合的特有方法【应用】
- 特有方法
方法名 说明
Object setProperty(String key, String value) 设置集合的键和值,都是String类型,底层调用 Hashtable方法 put
String getProperty(String key) 使用此属性列表中指定的键搜索属性
Set<String> stringPropertyNames() 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
-
示例代码
public class PropertiesDemo02 {
public static void main(String[] args) {
//创建集合对象
Properties prop = new Properties();
//Object setProperty(String key, String value):设置集合的键和值,都是String类型
prop.setProperty("itheima001", "佟丽娅");
prop.setProperty("itheima002", "赵丽颖");
prop.setProperty("itheima003", "刘诗诗");
//String getProperty(String key):使用此属性列表中指定的键搜索属性
// System.out.println(prop.getProperty("itheima001"));
// System.out.println(prop.getProperty("itheima0011"));
// System.out.println(prop);
//Set<String> stringPropertyNames():从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
Set<String> names = prop.stringPropertyNames();
for (String key : names) {
// System.out.println(key);
String value = prop.getProperty(key);
System.out.println(key + "," + value);
}
}
}
5.3Properties和IO流相结合的方法【应用】
- 和IO流结合的方法
方法名 说明
void load(Reader reader) 从输入字符流读取属性列表(键和元素对)
void store(Writer writer, String comments) 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流
-
示例代码
public class PropertiesDemo03 {
public static void main(String[] args) throws IOException {
//把集合中的数据保存到文件
// myStore();
//把文件中的数据加载到集合
myLoad();
}
private static void myLoad() throws IOException {
Properties prop = new Properties();
//void load(Reader reader):
FileReader fr = new FileReader("myOtherStream\\fw.txt");
prop.load(fr);
fr.close();
System.out.println(prop);
}
private static void myStore() throws IOException {
Properties prop = new Properties();
prop.setProperty("itheima001","佟丽娅");
prop.setProperty("itheima002","赵丽颖");
prop.setProperty("itheima003","刘诗诗");
//void store(Writer writer, String comments):
FileWriter fw = new FileWriter("myOtherStream\\fw.txt");
prop.store(fw,null);
fw.close();
}
}
File类
1File类概述和构造方法【应用】
- File类介绍
- 它是文件和目录路径名的抽象表示
- 文件和目录是可以通过File封装成对象的
- 对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已.它可以是存在的,也可以是不存在的.将来是要通过具体的操作把这个路径的内容转换为具体存在的
- File类的构造方法
方法名 说明
File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
File(String parent, String child) 从父路径名字符串和子路径名字符串创建新的 File实例
File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 File实例
-
示例代码
public class FileDemo01 {
public static void main(String[] args) {
//File(String pathname): 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
File f1 = new File("E:\itcast\java.txt");
System.out.println(f1);
//File(String parent, String child): 从父路径名字符串和子路径名字符串创建新的 File实例
File f2 = new File("E:\\itcast","java.txt");
System.out.println(f2);
//File(File parent, String child): 从父抽象路径名和子路径名字符串创建新的 File实例
File f3 = new File("E:\\itcast");
File f4 = new File(f3,"java.txt");
System.out.println(f4);
}
}
2绝对路径和相对路径【理解】
- 绝对路径 是一个完整的路径,从盘符开始
- 相对路径 是一个简化的路径,相对当前项目下的路径
3File类创建功能【应用】
- 方法分类
方法名 说明
public boolean createNewFile() 当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件
public boolean mkdir() 创建由此抽象路径名命名的目录
public boolean mkdirs() 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录
4File类删除功能【应用】
只能删除文件、空文件夹
- 方法分类
方法名 说明
public boolean delete() 删除由此抽象路径名表示的文件或目录
2.5File类判断和获取功能【应用】
- 判断功能
方法名 说明
public boolean isDirectory() 测试此抽象路径名表示的File是否为目录
public boolean isFile() 测试此抽象路径名表示的File是否为文件
public boolean exists() 测试此抽象路径名表示的File是否存在
- 获取功能
方法名 说明
public String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串
public String getPath() 将此抽象路径名转换为路径名字符串
public String getName() 返回由此抽象路径名表示的文件或目录的名称
public File[] listFiles() 返回此抽象路径名表示的目录中的文件和目录的File对象数组
getName()
如果调用者是文件,获取文件名和后缀名
如果调用者是文件夹,获取文件夹的名字