知识点:
字节操作流:OutputStream、InputStream
字符操作流:Reader、Writer
对象序列化:Serializable
File 类:
在整个 IO 包中,最重要的类就是一个 File 类,而且也只有 File 类是唯一与文件本身有关的操作类,与文件本身有关
指的是,文件的创建、删除、重命名、得到路径、创建时间等。
相关方法:
方法或常量名称 类型 描述
1 public static final String separator 常量 表示路径分隔符“\”
2 public static final String pathSeparator 常量 表示路径分隔,表示“;”
3 public File(String pathname) 构造 构造 File 类实例,要传入路径
4 public boolean createNewFile() throws IOException 普通 创建新文件
5 public boolean delete() 普通 删除文件
6 public String getParent() 普通 得到文件的上一级路径
7 public boolean isDirectory() 普通 判断给定的路径是否是文件夹
8 public boolean isFile() 普通 判断给定的路径是否是文件
9 public String[] list() 普通 列出文件夹中的文件
10 public File[] listFiles() 普通 列出文件夹中的所有文件
11 public boolean mkdir() 普通 创建新的文件夹
12 public boolean renameTo(File dest) 普通 为文件重命名
13 public long length() 普通 返回文件大小
File 类的相关操作 例子
1.创建文件 方法:使用 createNewFile()方法完成。
File file = new File("d:\\test.txt");
try {
file.createNewFile(); // 创建文件
} catch (IOException e) {
e.printStackTrace();
}
注:存在路径问题
windows 下。分隔符是“\”
linux 下。分隔符是“/”
解决:
File file = new File("d:" + File.separator + "test.txt");
2.删除文件 方法:使用 delete()方法进行文件的删除操作。
File file = new File("d:" + File.separator + "test.txt");
file.delete();// 删除文件
注:
以上确实可以删除文件,但是此时文件的执行速度较慢,会造成延迟,这一点在开发的时候一定要特别注意,往往
会因为文件有延迟而可能造成开发中出现的问题。
但是,以上的操作也存在些问题。以上是不管文件是否存在,就直接删除了,至少在删除之前要判断一下文件是否
存在之后再删除,所以使用 exists()方法判断文件是否存在。
File file = new File("d:" + File.separator + "test.txt");
if (file.exists()) { // 文件是否存在
file.delete();// 删除文件
3.判断类型:判断给定的路径是文件还是文件夹。
File file1 = new File("d:" + File.separator + "test.txt"); // 文件路径
File file2 = new File("d:"); // 文件夹路径
System.out.println(file1.isFile());
System.out.println(file2.isDirectory());
System.out.println("文件大小:" + file1.length());
System.out.println("文件路径:" + file1.getPath());
System.out.println("文件路径:" + file1);
4. 列出目录的内容:
如果现在给定了一个文件夹,要求可以将这个文件夹中的内容全部列出,此时,可以使用以下的两种方法:
第一种方法:public String[] list()
第二种方法:public File[] listFiles()
File file = new File("d:" + File.separator); // 文件夹路径
String str[] = file.list(); // 列出目录内容
for (int x = 0; x < str.length; x++) {
System.out.println(str[x]);
}
注:此方法列出的只是各个目录或文件的名称。
使用 listFiles()方法
File file = new File("d:" + File.separator); // 文件夹路径
File files[] = file.listFiles(); // 列出
for (int x = 0; x < files.length; x++) {
System.out.println(files[x]);
注:第二种方法列出的是全部的文件的完整路径,这样肯定更加适合操作,所以使用第二种方法比较合理。
输入和输出流
字节流:主要是操作字节数据(byte),分为 OutputStream,字节输出流、InputStream,字节输入流
字符流:主要是操作字符数据(char),分为 Writer,字符输出流,Reader,字符输入流
字节输出流:OutputStream:
法名称 类型 描述
1 public void close() throws IOException 普通 关闭
2 public void flush() throws IOException 普通 刷新操作
3 public void write(byte[] b) throws IOException 普通 将一组字节写入到输出流之中
4 public void write(byte[] b,int off,int len) throws IOException 普通 将指定范围的字节数组进行输出
5 public abstract void write(int b) throws IOException 普通 每次写入一个字节,byte int
但是,以上的类只是一个抽象类,抽象类必须通过子类完成,现在要向文件中输出,使用 FileOutputStrea
方法名称 类型 描述
1
public FileOutputStream(File file) throws
FileNotFoundException
构造 接收 File 类的实例,表示要操作的文件位置。
2
public FileOutputStream(File file,boolean append)
throws FileNotFoundException
构造 接收 File 类实例,并指定是否可以追加
File file = new File("D:" + File.separator + "test.txt"); // 指定要操作的文件
OutputStream out = null; // 定义字节输出流对象
try {
out = new FileOutputStream(file); // 实例化操作的父类对象
} catch (FileNotFoundException e) {
e.printStackTrace();
}
String info = "Hello World";// 要打印的信息
byte b[] = info.getBytes(); // 将字符串变为字节数组
try {
out.write(b);// 输出内容
} catch (IOException e) {
e.printStackTrace();
}
try {
out.close(); // 关闭
注:追加
out = new FileOutputStream(file, true); // 实例化操作的父类对象,可以追加内容
字节输入流:InputStream:
方法名称 类型 描述
1 public void close() throws IOException 普通 关闭
2 public abstract int read() throws IOException 普通 读取每一个字节
3 public int read(byte[] b) throws IOException 普通 向字节数组中读取,同时返回读取的个数
4 public int read(byte[] b,int off,int len) throws IOException 普通 指定读取的范围
InputStream 类本身属于抽象类,肯定需要子类支持,子类从文件中读取肯定是 FileInputStream。
方法名称 类型 描述
1 public FileInputStream(File file) throws FileNotFoundException 构造 通过 File 类实例,创建文件输入流
读取文件:
InputStream input = null; // 字节输入流
try {
input = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
byte[] b = new byte[1024];// 开辟byte数组空间,读取内容
int len = 0;
try {
len = input.read(b); // 读取
} catch (IOException e) {
e.printStackTrace();
}
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(new String(b, 0, len));
可以通过 read()方法采用循环读的方式:
byte b[] = new byte[1024];// 开辟byte数组空间,读取内容
int len = 0;
try {
int temp = 0; // 接收每次读取的内容
while ((temp = input.read()) != -1) {// 如果不为-1表示没有读到底
b[len] = (byte) temp; // int --> byte
len++;
注:以上方法开辟的空间可能很大,没必要开辟那么的空间
File file = new File("D:" + File.separator + "test.txt");// 要读取的文件路径
InputStream input = null; // 字节输入流
try {
input = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
byte b[] = new byte[(int) file.length()];// 根据文件大小,开辟byte数组空间
try {
input.read(b); // 读取
} catch (IOException e) {
e.printStackTrace();
}
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(new String(b));
字符输出流:Writer
方法名称 类型 描述
1 public void write(String str) throws IOException 普通 直接将字符串写入输出
2 public void write(char[] cbuf) throws IOException 普通 输出字符数组
3 public abstract void close() throws IOException 普通 关闭
4 public abstract void flush() throws IOException 普通 刷新
注:与 OutputStream 一样,使用 FileWriter 类完成操作,此类的构造方法如下:
方法名称 类型 描述
1 public FileWriter(File file) throws IOException 构造 根据 File 类构造 FileWriter 实例
2 public FileWriter(File file,boolean append) throws IOException 构造 根据 File 类构造 FileWriter 实例,可以追加内容
使用 Writer 完成文件内容的输出
File file = new File("D:" + File.separator + "test.txt"); // 指定要操作的文件
Writer out = null; // 定义字节输出流对象
out = new FileWriter(file); // 实例化操作的父类对象
String info = "Hello World!!!";// 要打印的信息
out.write(info);// 输出内容
out.close(); // 关闭
字符输入流:Reader
方法名称 类型 描述
1 public int read() throws IOException 普通 读取一个内容
2 public int read(char[] cbuf) throws IOException 普通 读取一组内容,返回读入的大小
3 public abstract void close() throws IOException 普通 关闭
此类,依然需要使用 FileReader 类进行实例化操作,FileReader 类中的构造方法定义如下:
方法名称 类型 描述
1 public FileReader(File file) throws FileNotFoundException 构造 接收 File 类的实例
File file = new File("D:" + File.separator + "test.txt");// 要读取的文件路径
Reader input = null; // 字节输入流
input = new FileReader(file);
char b[] = new char[1024];// 开辟char数组空间,读取内容
int len = input.read(b); // 读取
input.close();
System.out.println(new String(b, 0, len));
字节流和字符流的区别
区别:字节流没有使用到缓冲区,而是直接操作输出的,而字符流使用到了缓冲区,是通过缓冲区操作输出的。
File file = new File("D:" + File.separator + "test.txt"); // 指定要操作的文件
OutputStream out = null; // 定义字节输出流对象
out = new FileOutputStream(file); // 实例化操作的父类对象
String info = "Hello World!!!";// 要打印的信息
byte b[] = info.getBytes(); // 将字符串变为字节数组
out.write(b);// 输出内容
// 本程序没有进行关闭
此时,虽然没有关闭输出流,但是内容依然可以输出,证明,字节操作流是直接与输出本身有关的,那么如果现在
同样的操作使用字符流呢?
File file = new File("D:" + File.separator + "test.txt"); // 指定要操作的文件
Writer out = null; // 定义字节输出流对象
out = new FileWriter(file); // 实例化操作的父类对象
String info = "Hello World!!!";// 要打印的信息
out.write(info);// 输出内容
// 此处没有关闭
此时已经完成了程序,但是程序执行之后发现并没有任何的内容,因为所有的内容都放在缓冲区之中,只有在关闭
的时候才会清空缓冲区,进行输出,如果此时希望可以把内容输出的话,则必须手工调用 flush()方法完成。
File file = new File("D:" + File.separator + "test.txt"); // 指定要操作的文件
Writer out = null; // 定义字节输出流对象
out = new FileWriter(file); // 实例化操作的父类对象
String info = "Hello World!!!";// 要打印的信息
out.write(info);// 输出内容
out.flush();// 强制清空缓冲区
// 此处没有关闭
字节- 字符转换流
OutputStreamWriter:可以将输出的字符流变为字节流的输出形式
InputStreamReader:将输入的字节流变为字符流输入形式
打印流:PrintStream
打印流的主要功能是用于输出,在整个 IO 包中打印流分为两种类型:
字节打印流:PrintStream
字符打印流:PrintWriter
注:OutputStream 本身已经提供了很好的输出功能,但是使用 OutputStream 输出其他数据,例如:boolean、char、
float 等就比较麻烦了,所以在 Java 中为了方便输出,提供了专门的打印流。
方法名称 类型 描述
1 public PrintStream(OutputStream out) 构造 接收 OutputStream 类的实例。
2 public PrintStream(File file) throws FileNotFoundException 构造 接收 File 类实例,向文件中输出
3 public PrintStream format(String format, Object... args) 普通 表示格式化输出
4 public void print(数据类型 f) 普通 打印输出,不换行
5 public PrintStream printf(String format,Object... args) 普通 格式化输出
6 public void println(数据类型 f) 普通 打印输出,换行
注:从以上类的定义中可以发现,此类可以完成输出的功能,但是这个类的输出功能比直接使用 OutputStream 输出强,
因为可以输出任意的数据类型。也就是说此类实际上是将 OutputStream 加强了。
在此类的构造方法中,需要接收 OutputStream 类的实例,那么实际上此时就意味着,哪个子类为 PrintStream 实例化,
PrintStream 就具备了向指定位置的输出能力。
File file = new File("D:" + File.separator + "temp.txt");
OutputStream output = new FileOutputStream(file);
PrintStream out = new PrintStream(output);
out.print("hello");
out.print(" world ");
out.println("!!!");
out.print("1 X 1 = " + (1 * 1));
out.println("\n输出完毕");
out.close();
格式化的操作,则必须指定格式化的操作模板
模板标记 描述
1 %s 表示字符串
2 %d 表示整数
3 %n.mf 表示小数,一共的数字长度是 n,其中小数是 m 位
4 %c 表示字符
String name = "张三";
float salary = 800.897f;
int age = 10;
PrintStream out = new PrintStream(new FileOutputStream(new File("d:"
+ File.separator + "temp.txt")));
out.printf("姓名:%s,年龄:%d,工资:%7.2f。", name, age, salary);
对象序列化:
对象序列化就是指将一个对象转化成二进制的 byte 流。
将对象保存在文件上的操作称为对象的序列化操作
将对象从文件之中恢复称为反序列化的操作
Serializable 接口
注:此接口中没有任何的方法定义。与 Cloneable 接口一样,此接口也属于标识接口,表示可以被序列化。
虽然此接口中没有定义任何的方法,但是在操作的时候也不要让所有的类都实现此接口。只能在需要的地方进行实
现,因为现在接口中没有方法,并不表示以后的接口中同样没有方法。
public class Person implements Serializable {
/**
* 此常量表示的是一个序列化的版本编号,为的是可以在不同的JDK 版本间进行移植
*/
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
进行序列化操作:ObjectOutputStream
ObjectOutputStream 专门用于对象的输出操作
方法名称 类型 描述
1 public ObjectOutputStream(OutputStream out) throws IOException 构造 接收 OutputStream 实例,进行实例化操作
2 public final void writeObject(Object obj) throws IOException 普通 输出一个对象
3 public void close() throws IOException 普通 关闭
注:发现 ObjectOutputStream 类的使用与 PrintStream 非常类似,根据实例化其子类的不同,输出的位置也不同。
在使用 writeObject()方法的时候,发现使用 Object 进行参数的接收,那么证明所有的对象都可以使用此方法输出,都
会自动发生向上转型的关系。
将 Person 的对象保存在文件之中
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
new File("D:" + File.separator + "person.ser")));
Person per = new Person("张三", 30);
oos.writeObject(per);// 输出
oos.close();// 关闭
注:此时,对象已经被成功的序列化到了文件之中。
但是必须提醒的是,对象不一定只能序列化到文件之中,任何地方都有可能序列化,根据实例化 ObjectOutputStream
类的对象不同,输出的位置也不同。
进行反序列化操作:ObjectInputStream
方法名称 类型 描述
1
public ObjectInputStream(InputStream in) throws
IOException 构造 根据输入流的不同,实例哈 ObjectInputStream 类的
对象
2
public final Object readObject() throws
IOException,ClassNotFoundException
普通 读取对象
写入对象的时候所有的对象都向 Object 进行转型操作,所以读取的时候也使用 Object 进行读取的操作
进行对象的反序列化操作
ObjectInputStream oos = new ObjectInputStream(new FileInputStream(
new File("D:" + File.separator + "person.ser")));
Person p = (Person)oos.readObject() ;
System.out.println(p);
序列化一组对象
在序列化操作中,每次只能序列化一个对象,如果现在要想序列化一组对象该如何操作呢?
此时,可以采用 对象数组的形式,因为对象数组可以向 Object 进行转型操作。
Person per[] = { new Person("张三", 30), new Person("李四", 35),
new Person("王五", 50) };
ser(per); // 序列化一组对象
Person p[] = (Person[]) dser(); // 反序列化
for (int x = 0; x < p.length; x++) {
System.out.println(p[x]) ;
}
}
public static void ser(Object obj) throws Exception { // 所有异常抛出
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
new File("D:" + File.separator + "person.ser")));
oos.writeObject(obj);// 输出
oos.close();// 关闭
}
public static Object dser() throws Exception { // 所有异常抛出
ObjectInputStream oos = new ObjectInputStream(new FileInputStream(
new File("D:" + File.separator + "person.ser")));
Object obj = oos.readObject();
return obj;