1、IO流
IO流:数据传输过程类似于水流,故称IO流
IO流的的40多个类都是从4个抽象类基类中派生出来的,前者是字节,后者是字符
- InputStream/Reader:所有的输入流的基类
- OutputStream/Writer:所有输出流的基类
2、字符流和字节流的区别
- 字符流是由Java虚拟机将字节转换得到的,这个过程比较耗时,如果我们不知道编码类型就很容易出现问题
- Reader 用于读取文本, InputStream 用于读取原始字节
- 字符和字节的编码转换:utf8 :英文占 1 字节,中文占 3 字节,unicode:任何字符都占 2 个字节,gbk:英文占 1 字节,中文占 2 字节
3、字节流
1、InputStream(字节输入流)
1、InputStream: 用于从源头(通常是文件)读取数据(字节信息)到内存中
2、常用方法
- read():返回输入流中下一个字节的数据
- skip():忽略输入流的n个字节
- available():返回输入流中可以读取的字节数
- close():关闭输入流,释放相关的系统资源
- readAllBytes():读取输入流中的所有字节,返回字节数组
- transferTo(OutputStream out):将所有字节从一个输入流传递到一个输出流
3、常用子类
- FileInputStream:和文件相关的字节输入流类
import java.io.*;
public class FileStreamDemo {
public static void main(String[] args) {
try {
File file=new File("src\\aa.txt");
FileInputStream f1=new FileInputStream(file);//这里需要进行抛出异常处理
for (int i = 0; i < file.length(); i++) {
char ch=(char)(f1.read());//循环读取字符
System.out.print(ch+" ");
}
System.out.println();//换行操作
f1.close();//关闭文件
} catch (Exception e) {
// TODO: handle exception
System.out.println("文件打开失败");
}
}
}
- BufferedInputStream:字节缓存输入流
// 新建一个 BufferedInputStream 对象
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("input.txt"));
// 读取文件的内容并复制到 String 对象中
String result = new String(bufferedInputStream.readAllBytes());
System.out.println(result);
- DataInputStream:用于读取指定类型数据,不能单独使用,必须结合 FileInputStream
FileInputStream fileInputStream = new FileInputStream("input.txt");
//必须将fileInputStream作为构造参数才能使用
DataInputStream dataInputStream = new DataInputStream(fileInputStream);
//可以读取任意具体的类型数据
dataInputStream.readBoolean();
dataInputStream.readInt();
dataInputStream.readUTF();
- ObjectInputStream:用于从输入流中读取Java对象(反序列化)
ObjectInputStream input = new ObjectInputStream(new FileInputStream("object.data"));
MyClass object = (MyClass) input.readObject();
input.close();
2、OutputStream(字节输出流)
1、OutputStream: 用于将数据(字节信息)写入到目的地(通常是文件)
2、常用方法
- write(int b) :将特定字节写入输出流。
- flush() :刷新此输出流并强制写出所有缓冲的输出字节。
- close() :关闭输出流释放相关的系统资源。
3、常用子类
- FileOutputStream:最常用的字节输出流对象,可直接指定文件路径,可以直接输出单字节数据,也可以输出指定的字节数组
import java.io.*;
public class FileOuputDemo {
public static void main(String[] args) throws FileNotFoundException {
File file=new File("src\\aa.txt");
FileOutputStream f1=new FileOutputStream(file);//(file,true),这里有true的话,代表可以在文件后面追加内容
String str="I love coding";
byte[] buff=str.getBytes();//将字符串转换为字节数组
try {
f1.write(buff);//把字节数组的内容写进去文件
} catch (Exception e) {
// TODO: handle exception
}finally {
try {
f1.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
- BufferedOutputStream:字节缓冲输出流
FileOutputStream fileOutputStream = new FileOutputStream("output.txt");
BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream)
- DataOutputStream :用于写入指定类型数据,不能单独使用,必须结合 FileOutputStream
- ObjectOutputStream:将对象写入到输出流(序列化)
4、字符流
字符流默认采用的是 Unicode 编码,我们可以通过构造方法自定义编码
1、Reader(字符输入流)
1、Reader: 用于从源头(通常是文件)读取数据(字符信息)到内存中
2、常用方法:
- read() : 从输入流读取一个字符
- skip(long n) :忽略输入流中的 n 个字符 ,返回实际忽略的字符数。
- close() : 关闭输入流并释放相关的系统资源
3、常用子类
- FileReader:InputStreamReader 是字节流转换为字符流的桥梁,其子类 FileReader 是基于该基础上的封装,可以直接操作字符文件
import java.io.*;
public class FileReaderDemo {
public static void main(String[] args) {
File file=new File("src\\cc.txt");
FileReader f=null;//文件读取对象
BufferedReader f1=null;//字符流对象
try {
f=new FileReader(file);
f1=new BufferedReader(f);
//循环打印cc文件中的每行数据
String str=null;
while((str=f1.readLine())!=null) {
System.out.println(str);
}
} catch (Exception e) {
// TODO: handle exception
}finally {
try {
f1.close();
f.close();
} catch (Exception e2) {
// TODO: handle exception
}
}
}
}
2、Writer(字符输出流)
1、Writer: 用于将数据(字符信息)写入到目的地(通常是文件)
2、常用方法:
- write(int c) : 写入单个字符
- write(String str) :写入字符串
- append(char c) :将指定的字符附加到指定的 Writer 对象并返回该 Writer 对象
- flush() :刷新此输出流并强制写出所有缓冲的输出字符。
- close():关闭输出流释放相关的系统资源
3、常用子类
- FileWriter:OutputStreamWriter 是字符流转换为字节流的桥梁,其子类 FileWriter 是基于该基础上的封装,可以直接将字符写入到文件
import java.io.*;
public class FileWriterDemo {
public static void main(String[] args) {
String[] str= {"春眠不觉晓,","处处闻啼鸟,","夜来风雨声,","花落知多少,"};
File file=new File("src\\cc.txt");//我们在该类的位置创建一个新文件
FileWriter f=null;//创建文件写入对象
BufferedWriter f1=null;//创建字符流写入对象
try {
//这里把文件写入对象和字符流写入对象分开写了
f=new FileWriter("src\\cc.txt");//创建一个名为cc.txt的文件
f1=new BufferedWriter(f);
//通过循环遍历上面的String 数组中的元素
for (int i = 0; i < str.length; i++) {
f1.write(str[i]);//把String中的字符写入文件
f1.newLine();//换行操作
}
} catch (Exception e) {
// TODO: handle exception
}finally {//如果没有catch 异常,程序最终会执行到这里
try {
f1.close();
f.close();//关闭文件
} catch (Exception e2) {
// TODO: handle exception
}
}
}
}
5、字节缓冲流
1、字节缓冲流: IO 操作是很消耗性能的,缓冲流将数据加载至缓冲区,一次性读取/写入多个字节,从而避免频繁的 IO 操作,提高流的传输效率
2、和字节流的性能差别: 字节流和字节缓冲流的性能差别主要体现在我们使用两者的时候都是调用 write(int b) 和 read() 这两个一次只读取一个字节的方法的时候。由于字节缓冲流内部有缓冲区(字节数组),因此,字节缓冲流会先将读取到的字节存放在缓存区,大幅减少 IO 次数,提高读取效率
3、常用类: BufferedInputStream(字节缓冲输入流)和BurreredOutputStream(字节缓冲输出流)
6、字符缓冲流
BufferedReader (字符缓冲输入流)和 BufferedWriter(字符缓冲输出流): 类似于 BufferedInputStream(字节缓冲输入流)和BufferedOutputStream(字节缓冲输入流),内部都维护了一个字节数组作为缓冲区
7、打印流
- System.out 实际是用于获取一个 PrintStream 对象,print方法实际调用的是 PrintStream 对象的
write 方法。
System.out.println("Hello!");
- PrintStream 属于字节打印流,与之对应的是 PrintWriter (字符打印流)。
8、文件File类
- File类可以表示一个文件,还可以表示一个目录(Directory),所以我们可以在程序中用File 类的对象可以表示一个文件 或者 目录
- 当创建了 File 对象之后,我们可以利用该对象来对文件或者目录进行书属性修改:例如:文件的名称,修改日期的日期等等
- File 类的对象 还不能直接对文件进行读写操作,只能修改文件的属性
import java.io.*;
public class FileDemo {
public static void main(String[] args) {
File f1=new File("src\\aa.txt");//相对路径,如果没有前面的src,就在当前目录创建文件
if(f1.exists()) {
System.out.println("文件已经存在");
}else {
try {
f1.createNewFile();
System.out.println("文件创建成功");
} catch (Exception e) {
// TODO: handle exception
}
}
System.out.println("文件已经存在:"+f1.exists());
System.out.println("文件的名字:"+f1.getName());
System.out.println("文件的路径:"+f1.getPath());
System.out.println("文件的绝对路径:"+f1.getAbsolutePath());
System.out.println("是目录吗:"+f1.isDirectory());
System.out.println("文件大小:"+f1.length());
}
}
参考
- https://javaguide.cn/java/io/io-basis.html