文章目录
概述
形式上分为字节流和字符流,简单说:
- 字节流可以传任何东西
- 字符流只能传文本
功能上分为输入流和输出流
IO的东西在java.io包内
字节流
FileOutputStream/FileInputStream
所有的字节流类都以InputStream和OutputStream为超类
比如 ,向文件中写就要用FileOutputStream
new FileOutputStream(String path);//默认覆盖
new FileOutputStream(String path, boolean append);//是否是追加模式
new FileOutputStream(File f);//默认覆盖
new FileOutputStream(File f, boolean append);//是否是追加模式
FileOutputStream fs = new FileOutputStream(path);
byte[] b = "我觉得很好".getBytes();
fs.write(b);//这里用的是write(Bytes[])
fs.write(b, 2, 5);//从偏移量2开始写,写长度为5的bytes
fs.close();//关闭流并且释放相关资源(必须,否则一直开着资源用尽直接锁死)
注意字节流中的都是Byte,就算是write(int b)其实那个b也是字节
关于换行:
linux: \n
windows: \r\n
macos: \r
向文件中读就要用FileInputStream
FileInputStream fi = new FileInputStream(f);
//1、读一个字节,没数据了返回-1
char content = (char)fi.read();
//2、读取最多b.length个字节到b数组中,返回读了几个,读完以后再读返回-1
byte[] b = new byte[100];
int len = fi.read(b);
System.out.println(new String(b, 0, len));//String的构造可以接收byte数组
//3、从偏移量2开始读,读最多5个字节
int len = fi.read(b, 2, 5);
FileOutputStream和FileInputStream每次写一个字节都要调用系统服务,效率比较低,常用BufferedOutputStream和BufferedInputStream来改善
BufferedOutputStream/BufferedInputStream
内部有一个缓冲区数组,缓冲输入输出,减少底层系统调用
它的用法是包在其他的InputStream/OutputStream外面,它只提供缓冲功能,就像一个外接装备,而不是一个单独用的IO流
只需要close一次BufferedOutputStream/BufferedInputStream,不需要再对其包装的流去close了
FileInputStream fi = new FileInputStream("E:\\JavaLearningCode\\test\\out\\1.png");
FileOutputStream fo = new FileOutputStream("E:\\JavaLearningCode\\test\\out\\2.png", true);
BufferedInputStream fi1 = new BufferedInputStream(fi);
BufferedOutputStream fo1 = new BufferedOutputStream(fo);
//默认缓冲区大小为8192,也可以自己指定缓冲大小
BufferedInputStream fi1 = new BufferedInputStream(fi, 1024);
BufferedOutputStream fo1 = new BufferedOutputStream(fo, 1024);
fi1.close();
fo1.close();
字符流
字符流的超类是Reader和Writer
字符串编解码概述
GBK一个汉字2个字节,UTF-8一个汉字占3个字节,汉字在存储的时候第一个字节都是负数
String s = "江月何年初照人";
byte[] b1 = s.getBytes("UTF-8");
byte[] b2 = s.getBytes("GBK");
就可以把字符串编码成指定字符集形式
new String(b1, "UTF-8");
new String(b2, "GBK");
就可以按特定编码格式解码
InputStreamReader/OutputStreamWriter
自带缓冲区,也是个包装的类,挂靠在IO流上的
InputStreamReader接收字节流并且用字符集转成字符流
OutputStreamWriter使用字符集将字符流编码为字节流
OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream("./test.txt"), "GBK");
ow.write(-101);
ow.write("十年生死两茫茫");
ow.write("十年生死两茫茫",2,5);
byte[] b = "十年生死两茫茫".getBytes("GBK");
ow.write(b);
ow.write(b,2,5);
ow.flush();//调用这个方法把现在缓冲区里的内容交给底层字节流输出到目标位置
//工程中可以过一会刷一次,不至于程序崩溃的时候或者在流没有关闭的时候文件内是空的
ow.close();//也会自动执行一次flush
InputStreamWriter ir = new InputStreamWriter(new FileInputStream("./test.txt"), "GBK");
char[] buffer = new char[1024];
ir.read();
ir.read(buffer);
ir.read(buffer, 2, 50);
//读的三个方法和字节流相似,其实还能传入java.nio.CharBuffer
ir.close();
关于flush方法
- 这个flush是写在超类里的,下面的子类都继承了这个方法
- 但是无缓冲的流比如FileOutputStream只是把这个方法重写为空,就是用不上
- 有的流比如OutputStreamWriter和BuffererOutputStream包含缓冲区就可以用这个flush
- close虽然也有相同功能,但是close之后这个流就不能用了,所以用flush
FileWriter/FileReader
类似FileOutputStream和FileInputStream
FileWriter fw = new FileWriter("./test.txt", true);
BufferedWriter/BufferedReader
类似BufferedOutputStream和BufferedInputStream,提供缓冲,是套在别的Writer和Reader上用的,外接装备
BufferedOutputStream bops = new BufferedOutputStream(new FileWriter("./test.txt", true));
bops.flush();
特有功能
bos.newLine();//写换行符
bis.readLine();//读一行文字,不包括行终止符,如果已经到结尾返回null
流异常处理
JDK7之后有专门的流异常处理,自动释放流,可以不用throws
try(FileInputStream fi = new FileInputStream("E:\\JavaLearningCode\\test\\out\\1.png");
FileOutputStream fo = new FileOutputStream("E:\\JavaLearningCode\\test\\out\\2.png", true);){
一些操作..........
}catch(IOException e){
e.printStackTrace();
}
最后流会自动释放,不需要再写一个finally去close
JDK9之后又可以把流定义放外面,需要throws
FileInputStream fi = new FileInputStream("E:\\JavaLearningCode\\test\\out\\1.png");
FileOutputStream fo = new FileOutputStream("E:\\JavaLearningCode\\test\\out\\2.png", true);
try(fi; fo){
一些操作..........
}catch(IOException e){
e.printStackTrace();
}
标准输入输出流STDIO
System类有两个静态IO流
- System.in:一个InputStream对象,所有输入流的父类,通常是键盘输入,也可用户指定输入源
- System.out:一个PrintStream对象,父类是FilterOutputStream,通常是显示输出,也可用户指定输出目标
打印流
不用管给的数据是什么类型,都能打,很方便
1、字节打印流PrintStream
2、字符打印流PrintWriter:
- 特有方法println、printf
- print、println、printf时会自动flush刷新
- println = 写+换行+flush
装饰设计模式,包装在其他输出流外面
PrintStream ps = new PrintStream(OutputStream);
PrintWriter ps = new PrintWriter(OutputStream);
使用字符打印流复制文件
BufferedReader br = new BufferedReader(new FileReader("./test.java"));
PrintWriter pw = new PrintWriter(new FileWriter("./test2.java"));
String line;
while((line=br.readLine())!=null)
pw.println(line);
pw.close();
br.close();