IO流
-
Input:输入流 Output:输出流
-
java中流的命名:功能+ 类型
-
字符流:操作字符:只能操作普通文本文件:常见的文本文件(.doc ppt等文件不是文本文件)
-
字节流:操作字节,能操作一切文件(文本文件,mp3,视频,ppt,doc)
-
字符输入流:共同父类Reader:比如子类:FileReader,BufferedReader
功能:读取一个字符,读取一个字符数组
-
字符输出流:共同的父类:Writer 比如子类: FileWriter BufferedWriter
功能:写一个字符,写一个字符数组,写一个字符串,写入一个字符的某一个部分
-
字节输入流:共同父类:InputStream 比如:FileInputStream BufferedInputStream
功能:读取一个字节,读取一个字节数组
-
字节输出流:共同父类:OutputStream比如:FileOutputStream BufferedOutputStream
功能:写一个字节,写一个字节数组,写一个字节数组一部分
-
理解:一切均为字节,在数据传输过程中,一切数据最终存储为一个个字节,即二进制数字,所以数据传输过程中使用二进制数据可以完成任意数据的传递,我们向一个文件中存储一定的数据(一些数字),如果使用文本方式打开,则会以文本的方式解释数据。如果有以视频的方式打开,则会以视频的方式解释数据。所以在文件传输的过程中,传输的始终为二进制数据
-
字节输出流:OutputStream:字节输出流的根类,抽象类:
- public void close();//关闭流
- public void flush();//刷新流
- public void write(int b);//写一个字节
- public void write(byte[] bs);写一个字节数组
- publlic void write(byte[] bs,int x,int y)写入字节数组的一部分
- 在字节输出流定义对象的时候,有一个参数:bool flag 如果为true则是追加,反之是覆盖,默认是false
-
字节输入流:InputStream:字节输入流的根类,是一个抽象类
- public int read()//读取一个字节,返回的是码值
- public int read(byte[] bs)//读取一个字节数组,返回值表示实际读取到的字节数
- 实际上在给字节输入流实例化对象的时候,参数是文件,如果这个文件不存在,直接会抛出异常
字节缓冲流
-
分类:
- 写入数据到流中,字节缓冲输出流, BufferedOutputStream
- 读取流中的数据, 字节缓冲输入流 BufferedinputStream
- 它们的内部都包含一个缓冲区,通过缓冲区读写,可以提高IO流读写速度
-
BufferedOutputStream 缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("1.txt")); 通过这句话可以理解到,BufferedOutputStream就是FileOutputStream的某一个子类
-
字节缓冲输入流用法几乎一样
复制单级文件夹
-
复制文件夹,没有一个专门的流进行
package java学习.IO流; import java.io.*; //赋值单级文件夹实验 /*1. 文件源给出:/home/ach/IdeaProjects/untitled/src/java学习/has 2. 目标文件夹:随意 条件:1. 源文件夹必须存在 2. 目标文件夹可能存在,可能不存在 3. 获取picture中所有file对象数组 4. 遍历数组,保持文件夹一致性 5. 提示某个文件保存成功 */ public class Test5 { public static void main(String[] args) { //先定义一个源文件夹和目标文件夹 File fileSrc = new File("/home/ach/IdeaProjects/untitled/src/java学习/has"); File fileObj = new File("/home/ach/IdeaProjects/untitled/src/java学习/mode"); //判断目标文件夹是否存在 if (!fileObj.exists()){ boolean b = fileObj.mkdir(); if (b){ System.out.println("目标文件夹不存在,创建成功"); } }else{ System.out.println("目标文件夹已经存在"); } //列出源文件夹下所有文件 File[] files = fileSrc.listFiles(); for (File file:files) { //遍历出一个文件,需要复制一个文件 File obj = new File(fileObj,file.getName()); //复制文件 System.out.println(obj); try { copyFile(file, obj); }catch (Exception e){ System.out.println("复制文件"+file.getName()+"失败"); } } System.out.println("文件夹复制成功"); } public static void copyFile(File file1,File file2) throws IOException{ //创建两个缓冲流对象 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file1)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file2)); byte[] bs = new byte[1024]; int len = 0; while ((len = bis.read(bs)) != -1) { bos.write(bs, 0, len); } bos.close(); bis.close(); System.out.println("复制文件" + file1.getName() + "成功"); } }
-
使用字节流读取中文乱码问题
[外链图片转存失败(img-p2QP3WVv-1562332984712)(/home/ach/Pictures/2019-03-18 17-20-11 的屏幕截图.png)]
总结
-
FileInputStream:
-
读取数据方法 read
-
标准代码
方法一 int b = 0; while((b=fis.read())!=-1){ sout((char)b) } 方法二: byte[] bs = new byte[1024]; int len = 0; while((len=fis.read(bs))!=-1){ String s = new String(bs,0,len); sout(s); }
-
写数据:写一个字节、写一个字节数组、一次写一个字节数组的一部分
-
字节缓冲流的用法基于字节流
-
字符编码表:
- ASCLL码表,保存了数字,字母,以及一些符号,对应的数字
- GB2312码表,保存常用的汉字,一个中文占用两个字节,而且这两个字节都是负数
- GBK码表:保存了基本所有的汉字,不管是英文还是中文,统统都是两个字节
- Unicode:统一码表,所有的字节都是统统两个字节
- utf-8:在Unicode的基础上进行优化:一个字节能处理的数据,不用两个字节储存,而且这个码表更加标准化,一个中文3个字节
- ISO-8859-1:拉丁码表,Tomcat专用
-
转换流(可以避免的中文乱码问题,因为码表是utf-8或者gbk,字节区别)
-
快递运输:
[外链图片转存失败(img-3sprgphr-1562332984713)(/home/ach/Pictures/2019-03-19 15-25-43 的屏幕截图.png)]
-
OutputStreamWriter:是一个字符流,继承Writer,是字符流通向字节流的桥梁,输出流,功能就是编码,查码表
[外链图片转存失败(img-De8Sx6ax-1562332984713)(/home/ach/Pictures/2019-03-19 15-35-16 的屏幕截图.png)]
-
public OutputStreamWriter(OutputStream out)从这里可以理解,返回一个字节流
public static void main(String[] args) throws Exception { //创建一个OutputStreamWriter对象 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("1.txt")); //写入数据 osw.write("你好"); //关闭流 osw.close(); }
-
同时,这个对象的实例化的对象使用的方法是字节输出流的方法
-
-
InputStreamReader:字符流,继承reader类,是字节流通向字符流的方法,查码表
[外链图片转存失败(img-eBnUNLBU-1562332984713)(/home/ach/Pictures/2019-03-19 15-47-17 的屏幕截图.png)]
- public InputStreamReader(InputStream in),从这里可以理解,返回一个字符流,默认查询gbk码表
- public InputStreamReader(InputStream in,String …)多一个参数进行确定编码表类型是gbk还是utf-8
- 父类和子类的区别:OutputStreamWriter和InputStreamReader两个类是字符和字节的桥梁,也可以称为字符转换流,他们的子类FileWriter和FileReader 作为子类,仅作为操作字符文件的便捷雷存在,当操作的字符文件,使用的是默认编码表时候可以不用父类,而直接用子类就可以完成操作
序列化流和反序列化流
- 序列化流:写对象到文件,ObjectOutputStream
- public ObjectOutputStream(OutputStream out)
- public void writerObject(Object obj)//这个方法会抛出异常NotSerializableException,需要实现其序列化功能的接口SerializableException,这个接口中没有方法,但是需要标记,如果一个类有标记才可以序列化
- 反序列化流:从文件中读取对象,ObjectInputStream
- public ObjectInputStream(InputStream ois)
- 当写完一个对象后,修改该对象所属的类,那么再次读取对象的时候,原来的类失效,这时候会出翔无效类异常
- jvm如何判断一个类是否有效,当你写完一个类的时候类的内部有一个版本好,当你修改类的时候版本好会发生变化
- transient:关键字作用,用来修饰成员变量,用不用transient修饰对成员变量完全没有影响,但是在序列化的时候,如果一个成员变量被transient修饰,那么序列化时候会忽略该成员变量
- static:它也具有和transient一样的功能,只不过static功能不是单一而已
打印流
- PrintWriter:打印字符流 PrintStream:打印字节流
- PrintWrite和PrintStream
- 用法几乎一样
- 区别在于打印的目的地不一样:
- PrintStream:字符串的文件名、File对象、其他OutputStream流
- PrintWriter:字符串的文件名、File对象、其他的OutputStream流、其他的Writer流