文章目录
一.简介
本文介绍了Java中IO相关的知识内容,包括File类操作、文件过滤器、各类输入输出流(字节流、字符流、缓冲流、转换流、打印流)以及序列化和反序列化。
二.File类
File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作。
常用构造方法如下:
- 绝对路径:从盘符开始的路径,这是一个完整的路径。
- 相对路径:相对于项目目录的路径,这是一个便捷的路径,开发中经常使用。
// 文件路径名
String pathname1 = "D:\\aaa.txt";//绝对路径
File file1 = new File(pathname);
// 文件路径名
String pathname2 = "aaa.txt";//相对路径
File file2 = new File(pathname2);
// 通过父路径和子路径字符串
String parent = "D:\\aaa";
String child = "bbb.txt";
File file3 = new File(parent, child);
// 通过父级File对象和子路径字符串
File parentDir = new File("D:\\aaa");
String child = "bbb.txt";
File file4 = new File(parentDir, child);
常用API:
public String getName() 获取名称
public File getParentFile() 、public String getParent() 获得父项
public String getPath() 获取路径名称
public String getAbsolutePath() 获取绝对路径名称
public boolean exists() 判断是否存在
public boolean createNewFile() 创建新文件
public boolean mkdir()、public boolean mkdirs() 创建多级目录
public boolean isDirectory() 是否是目录
public boolean isFile() 是否是文件
public long lastModified() 获取最后修改的时间
public long length() 获取长度
public boolean delete() 删除
文件过滤器:
public String[] list() 列举当前文件夹下所有文件及目录的名字
public File[] listFiles() 列举当前文件夹下所有文件及目录的File对象
public String[] list(FilenameFilter filter)
public File[] listFiles(FilenameFilter filter)
public File[] listFiles(FileFilter filter)
三.IO
Java中I/O操作主要是指使用java.io包下的内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做写出数据。
IO的分类:
根据数据的流向分为:输入流和输出流。
- 输入流 :把数据从其他设备上读取到内存中的流。
- 输出流 :把数据从内存中写出到其他设备上的流。
根据数据的编码分为:字节流和字符流。
- 字节流 :以字节为单位,读写数据的流。例如:图片、音视频为主
- 字符流 :以字符为单位,读写数据的流。例如:文本为主
根据流的包装对象分为:节点流和处理流
- 节点流 :包装对象是特定的数据源,例如File对象、字符串或者是数组
- 处理流:包装对象是其它流对象,例如FileInputStream等流对象
顶级父类:
四.字节流
4.1 FileInputStream类
FileInputStream类是文件输入流,从文件中按字节读取到内存。
构造方法:
常用API:
public int read() 一个一个字节读取
public int read(byte b[]) 根据指定的字节数组,读取数据
public int read(byte b[], int off, int len) 根据指定的字节数组,读取数据
public void close() 关闭资源
//read方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回-1
public class FISRead {
public static void main(String[] args) throws IOException{
// 使用文件名称创建流对象
FileInputStream fis = new FileInputStream("aaa.txt");//abcde
// 定义变量,保存数据
int b ;
// 循环读取
while ((b = fis.read())!=-1) {
System.out.println((char)b);
}
// 关闭资源
fis.close();
}
}
输出结果:
a
b
c
d
e
//每次读取字节数组b的长度个字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回-1
public class FISRead {
public static void main(String[] args) throws IOException{
// 使用文件名称创建流对象.
FileInputStream fis = new FileInputStream("aaa.txt"); // 文件中为abcde
// 定义变量,作为有效个数
int len ;
// 定义字节数组,作为装字节数据的容器
byte[] b = new byte[2];
// 循环读取
while (( len= fis.read(b))!=-1) {
// 每次读取后,把数组变成字符串打印
System.out.println(new String(b));
}
// 关闭资源
fis.close();
}
}
输出结果:
ab
cd
ed
//错误数据d,是由于最后一次读取时,只读取一个字节e,数组中,上次读取的数据没有被完全替换,所以要通过len ,获取有效的字节,只需将输出修改为:
System.out.println(new String(b,0,len)); // 每次读取后,把数组的有效字节部分,变成字符串打印
4.2 FileOutputStream类
FileOutputStream类是文件输出流,从内存按字节写出到文件。
构造方法:
public FileOutputStream(File file)
public FileOutputStream(String name)
public FileOutputStream(File file, boolean append)
public FileOutputStream(String name, boolean append)
其中布尔值true 表示追加数据,false 表示清空原有数据。
常用API:
public void write(int b) 按照一个一个字节写数据
public void write(byte b[]) 按照字节数组,写数据
public void write(byte b[], int off, int len) 第一个参数是字节数组,第二个参数是起始位置,第三个参数是写出长度
public void close() 关闭资源
public void flush() 刷新资源
public class FOSWrite {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("aaa.txt");
fos.write(97); // 写出第1个字节
fos.write(98); // 写出第2个字节
fos.write(99); // 写出第3个字节
// 关闭资源
fos.close();
}
}
输出结果:
abc
public class FOSWrite {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("aaa.txt");
byte[] b = "你好".getBytes();//字符串转字节数组
// 写出字节数组数据
fos.write(b);
// 关闭资源
fos.close();
}
}
输出结果:
你好
//写出指定长度字节数组:write(byte[] b, int off, int len) ,每次写出从off索引开始,len个字节
public class FOSWrite {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("aaa.txt");
byte[] b = "abcde".getBytes();//字符串转字节数组
// 写出从索引2开始,2个字节。
fos.write(b,2,2);
// 关闭资源
fos.close();
}
}
输出结果:
cd
五.字符流
5.1 FileReader类
FileReader类是文件输入流,从文件按字符读取到内存。
FileReader(File file): 创建一个新的 FileReader ,给定要读取的File对象。
FileReader(String fileName): 创建一个新的 FileReader ,给定要读取的文件的名称。
常用API:
public int read()
public int read(char cbuf[], int offset, int length)
public void close()
//read方法,每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回-1。
public class FRRead {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileReader fr = new FileReader("aaa.txt");//你好
// 定义变量,保存数据
int b;
// 循环读取
while ((b = fr.read())!=-1) {
System.out.println((char)b);
}
// 关闭资源
fr.close();
}
}
输出结果:
你
好
//read(char[] cbuf),每次读取字符数组cbuf的长度个字符到数组中,返回读取到的有效字符个数,读取到末尾时,返回-1。
public class FRRead {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileReader fr = new FileReader("aaa.txt");//你好中国哈
// 定义变量,保存有效字符个数
int len;
// 定义字符数组,作为装字符数据的容器
char[] cbuf = new char[2];
// 循环读取
while ((len = fr.read(cbuf))!=-1) {
System.out.println(new String(cbuf));
}
// 关闭资源
fr.close();
}
}
输出结果:
你好
中国
哈国
获取有效的字符改进,代码如下:
public class FISRead {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileReader fr = new FileReader("aaa.txt");//你好中国哈
// 定义变量,保存有效字符个数
int len;
// 定义字符数组,作为装字符数据的容器
char[] cbuf = new char[2];
// 循环读取
while ((len = fr.read(cbuf))!=-1) {
System.out.println(new String(cbuf,0,len));
}
// 关闭资源
fr.close();
}
}
输出结果:
你好
中国
哈
5.2 FileWriter类
FileWriter类是文件输出流,从内存按字符写出到文件。
构造方法:
public FileWriter(File file)
public FileWriter(File file, boolean append)
public FileWriter(String fileName)
public FileWriter(String fileName, boolean append)
其中布尔值true 表示追加数据,false 表示清空原有数据。
常用API:
public void write(int c) 一个一个字符写
public void write(char cbuf[])按照字符数组写数据
public void write(char cbuf[], int off, int len) 按照字符数组写数据,第一个参数字符数组,第二个参数起始值,第三个参数写的长度
public void write(String str, int off, int len) 按照字符串写数据,第一个参数字符串,第二个参数起始值,第三个参数写的长度
public void write(String str) 按照字符串写数据
public void flush() 刷新
public void close() 关闭
//write(int b) 方法,每次可以写出一个字符数据
public class FWWrite {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileWriter fw = new FileWriter("aaa.txt");
fw.write(97); // 写出第1个字符
fw.write('b'); // 写出第2个字符
fw.write('C'); // 写出第3个字符
fw.write(30000); // 写出第4个字符,中文编码表中30000对应一个汉字。
fw.close();
/*
【注意】关闭资源时,与FileOutputStream不同。
如果不关闭,数据只是保存到缓冲区,并未保存到文件。
*/
}
}
//write(char[] cbuf) 和 write(char[] cbuf, int off, int len) ,每次可以写出字符数组中的数据。
public class FWWrite {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileWriter fw = new FileWriter("aaa.txt");
char[] chars = "今天星期五".toCharArray();//字符串转字符数组
// 写出字符数组
fw.write(chars); // 今天星期五
// 写出从索引2开始,2个字符。
fw.write(b,2,2); // 星期
// 关闭资源
fw.close();
}
}
//write(String str) 和 write(String str, int off, int len) ,每次可以写出字符串中的数据,更为方便。
public class FWWrite {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileWriter fw = new FileWriter("aaa.txt");
String msg = "今天星期五";
fw.write(msg); //今天星期五
// 写出从索引2开始,2个字符。
fw.write(msg,2,2); //星期
// 关闭资源
fw.close();
}
}
六.缓冲流
缓冲流,也叫高效流,是对4个基本的FileXxx 流的增强,所以也是4个流,按照数据类型分类:
- 字节缓冲流:BufferedInputStream,BufferedOutputStream
- 字符缓冲流:BufferedReader,BufferedWriter
缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
6.1 字节缓冲流
- public BufferedInputStream(InputStream in) :创建一个缓冲字节输入流。
- public BufferedOutputStream(OutputStream out): 创建一个缓冲字节输出流。
// 创建字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bis.txt"));
// 创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bos.txt"));
字节缓冲流读写方法与普通字节流是一致的。
6.2 字符缓冲流
- public BufferedReader(Reader in) :创建一个缓冲字符输入流。
- public BufferedWriter(Writer out): 创建一个缓冲字符输出流。
// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("br.txt"));
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
字符缓冲流的读写方法与普通字符流调用方式一致。特有方法如下:
- BufferedReader:public String readLine(): 读取一行。
- BufferedWriter:public void newLine(): 写出换行符 \n
//使用JDK7优化后的try-with-resource 语句,该语句确保了每个资源在语句结束时关闭。
/*try(
//资源类 implements Closeable
//创建资源类的对象,用完即关闭,但是不允许放无关资源类的代码
){
//代码
}catch(Exception e){
//捕捉异常
}
*/
public class BufferedReaderDemo {
public static void main(String[] args) {
try (
// 创建流对象
BufferedReader br = new BufferedReader(new FileReader("in.txt"))
) {
// 定义字符串,保存读取的一行文字
String line = null;
// 循环读取,读取到最后返回null
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
in.txt文件中的内容为:
你好
世界
!
输出结果为:
你好
世界
!
public class BufferedWriterDemo {
public static void main(String[] args) {
try (
// 创建流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));
) {
// 写出数据
bw.write("今天");
// 写出换行
bw.newLine();
bw.write("星期");
bw.newLine();
bw.write("五");
bw.newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//out.txt文件中的内容为:
今天
星期
五
七.转换流
7.1 InputStreamReader类
- public InputStreamReader(InputStream in) 默认UTF-8编码集,将字节流转成字符流
- public InputStreamReader(InputStream in, String charsetName) 根据指定编码集,将字节流转成字符流
InputStreamReader isr1 = new InputStreamReader(new FileInputStream("in.txt"));
InputStreamReader isr2 = new InputStreamReader(new FileInputStream("in.txt") , "GBK");
7.2 OutputStreamWriter类
- public OutputStreamWriter(OutputStream out) 默认UTF-8编码集,将字节流转换成字符流
- public OutputStreamWriter(OutputStream out, String charsetName) 按照指定编码集,将字节流转换成字符流
OutputStreamWriter isr1 = new OutputStreamWriter(new FileOutputStream("out.txt"));
OutputStreamWriter isr2 = new OutputStreamWriter(new FileOutputStream("out.txt") , "GBK");
八.打印流
8.1 PrintStream类
构造方法:
- public PrintStream(File file) 直接指定文件
- public PrintStream(File file, String csn) 直接指定文件,且指定编码集
- public PrintStream(String fileName) 直接指定文件名
- public PrintStream(String fileName, String csn) 直接指定文件名,且指定编码集
- public PrintStream(OutputStream out)
常用API:
- public void println() 换行
- public void println(String x) 写出字符串,且换行
- public void print(String s) 写出字符串,且不换行
打印流,用其改变流的输出方向
- System.setOut(PrintStream ps)
- System.setErr(PrintStream ps)
8.2 PrintWriter类
构造方法:
- public PrintWriter(String fileName) 直接指定文件名
- public PrintWriter(File file, String csn) 直接指定文件,且指定编码集
- public PrintWriter(OutputStream out)
- public PrintWriter (Writer out)
常用API:
- public void println(String x) 写出字符串,且换行
- public void print(String x) 写出字符串,且不换行
九.序列化和反序列化
Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据、对象的类型和对象中存储的属性等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。对象的数据、对象的类型和对象中存储的数据信息,都可以用来在内存中创建对象。
9.1 ObjectOutputStream类
ObjectOutputStream 类,将Java对象的原始数据类型写出到文件,实现对象的持久存储。
构造方法:
- public ObjectOutputStream(OutputStream out): 创建一个指定OutputStream的ObjectOutputStream。
FileOutputStream fileOut = new FileOutputStream("employee.txt");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
一个对象要想序列化,该类必须实现java.io.Serializable 接口。
序列化时,哪些方式可以确保属性不被序列化至文本介质中?
- 方式一:static 静态修饰符
- 方式二:transient 瞬态修饰符
- 方式三:public interface Externalizable extends java.io.Serializable
该类实现Externalizable接口,重写writeExternal(ObjectOutput out)和readExternal(ObjectInput in)方法,选择需要序列化和反序列化的属性。
写出对象的方法:
- public final void writeObject (Object obj) : 将指定的对象写出。
9.2 ObjectInputStream类
ObjectInputStream反序列化流,将之前使用ObjectOutputStream序列化的原始数据恢复为对象。
构造方法:
- public ObjectInputStream(InputStream in): 创建一个指定InputStream的ObjectInputStream。
重构对象的方法:
- public final Object readObject () : 读取一个对象。