java IO流

流的概念

内存与存储设备之间传输数据的通道

流的分类

按方向分:

  • 输入流:将<存储设备>中的内容读入到<内存>中

  • 输出流:将<内存中的内容写入到<存储设备>中

按单位分:

  • 字节流:以字节为单位,可以读写所有数据

  • 字符流:以字符为单位,只能读写文本数据

按功能分:

  • 节点流:具有实际传输数据的读写功能

  • 过滤流:在节点流的基础上增强功能

字节流

字节流的父类(抽象类)

  • InputStream:字节输入流

    • public int read(){}

    • public int read(byte[] b){}

    • public int read(byte[] b, int off, int len){}

  • OutputSream:字节输出流

    • public void write(int n){}

    • public void write(byte[] b){}

    • public void write(byte[] b, int off, int len){}

文件字节流

  • FileInputStream:

    • public int read(byte[] b) //从流中读取多个字节,将读到内容存入b数组,返回实际读到的字节数;如果到达文件尾部,则返回-1

    public class Demo1 {

       public static void main(String[] args) throws Exception{
           //1 创建FileInputStream,并指定文件路径
           FileInputStream fis = new FileInputStream("d:\\aaa.txt");
           //2 读取文件
           //2.1 单个字节读取
           int data = 0;
           while((data = fis.read())!=-1){
               System.out.println((char)data);
          }
           //2.2 多个字节读取
           byte[] buf = new byte[1024];
           int count = 0;
           while ((count = fis.read(buf))!=-1){
               System.out.println(new String(buf,0,count));
          }
           //3 关闭
           fis.close();
      }
    }

     

  • FileOutputSream:

    • public void write(byte[] b) //一次写入多个字节,将b数组中所有字节,写入输出流

    public class Demo1 {

       public static void main(String[] args) throws Exception {
           //1 创建FileOutputStream,并指定文件路径
           FileOutputStream fos = new FileOutputStream("d:\\aaa.txt",true);
           //true则表示文件可以继续写而不会被覆盖,默认为false
           //2 写入文件
           fos.write(97);
           fos.write('b');
           fos.write('c');

           String string = "helloworld";
           fos.write(string.getBytes());
           //3 关闭
           fos.close();
      }
    }

文件复制(案例)

public class Demo1 {

   public static void main(String[] args) throws Exception {
       FileInputStream fis = new FileInputStream("d:\\001.jpg");
       FileOutputStream fos = new FileOutputStream("d:\\002.jpg");

       byte[] buf = new byte[1024];
       int count = 0;
       while ((count=fis.read(buf))!=-1){
           fos.write(buf,0,count);
      }
       
       fos.close();
       fis.close();
  }
}

字节缓冲流

  • 缓冲流:BufferedInputStream/BufferedOutputStream

    • 提高IO效率,减少磁盘访问次数

    • 数据存储在缓存区中,flush是将缓存区的内容写入文件中,也可以直接close

  • 读文件

public class Demo1 {
   public static void main(String[] args) throws Exception{
       FileInputStream fis = new FileInputStream("d:\\aaa.txt");
       BufferedInputStream bis = new BufferedInputStream(fis);

       int data = 0;
       while ((data= bis.read())!=-1){
           System.out.println((char)data);
      }
       //也可以自己创建一个缓存区
       byte[] buf = new byte[1024];
       int count = 0;
       while ((count = bis.read(buf))!=-1){
           System.out.println(new String(buf,0,count));
      }

       bis.close();
  }
}
  • 写文件

public class Demo1 {
   public static void main(String[] args) throws Exception{
       FileOutputStream fos = new FileOutputStream("d:\\buffer.txt");
       BufferedOutputStream bos = new BufferedOutputStream(fos);

       for (int i = 0; i < 10; i++) {
           bos.write("helloworld".getBytes());//写入8K缓存区
           bos.flush();//刷新到硬盘
      }
//close内部会调用flush方法
       bos.close();
  }
}

对象流

对象流:ObjectInputStream/ObjectOutputStream

  • 增强了缓冲区功能

  • 增强了读写8种基本数据类型和字符串功能

  • 增强了读写对象的功能

    • readObject() 从流中读取一个对象(反序列化)

    • writeObject(Object obj) 向流中写入一个对象(序列化)

学生类

public class student implements Serializable {//实现Serializable接口
   private String name;
   private int age;

   public student(String name, int age) {
       this.name = name;
       this.age = age;
  }

   public String getName() {
       return name;
  }

   public void setName(String name) {
       this.name = name;
  }

   public int getAge() {
       return age;
  }

   public void setAge(int age) {
       this.age = age;
  }

   @Override
   public String toString() {
       return "student{" + "name='" + name + '\'' + ", age=" + age + '}';
  }
}

序列化

/**
* 要求:序列化的类必须要实现Serializable接口
*/
public class Demo1 {
   public static void main(String[] args) throws Exception{
       //1 创建对象流
       FileOutputStream fos = new FileOutputStream("d:\\stu.bin");
       ObjectOutputStream oos = new ObjectOutputStream(fos);
       //2 序列化(写入操作)
       student zhangsan = new student("张三",20);
       oos.writeObject(zhangsan);
       //3 关闭
       oos.close();
  }
}

反序列化

public class Demo1 {
   public static void main(String[] args) throws Exception {
       //创建对象流
       FileInputStream fis = new FileInputStream("d:\\stu.bin");
       ObjectInputStream ois = new ObjectInputStream(fis);
       //读取文件
       student s = (student) ois.readObject();
       //关闭
       ois.close();
       System.out.println(s.toString());
  }
}

序列化和反序列化注意事项

  • 序列化的类必须要实现Serializable接口

  • 序列化的类中的对象属性也要求实现Serializable接口

  • serialVersionUID:序列化版本号ID,保证序列化的类和反序列化的类是同一个类

private static final long serialVersionUID = 100L;//这个数值是可以自定义的
  • 使用transient(瞬间的)修饰属性,这个属性就不能被序列化

  • 静态属性不能序列化

  • 序列化多个对象时,可以借助集合实现

public class Demo1 {
public static void main(String[] args) throws Exception {
//1 创建对象流
FileOutputStream fos = new FileOutputStream("d:\\stu.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//2 序列化(写入操作)
student zhangsan = new student("张三", 20);
student lisi = new student("李四", 22);
// oos.writeObject(zhangsan);
// oos.writeObject(lisi);
ArrayList<student> list = new ArrayList<>();
list.add(zhangsan);
list.add(lisi);
oos.writeObject(list);

oos.close();
}
}
public class Demo2 {
public static void main(String[] args) throws Exception{
FileInputStream fis = new FileInputStream("d:\\stu.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
//读取文件
ArrayList<student> list = (ArrayList<student>) ois.readObject();
//关闭
ois.close();
System.out.println(list.toString());
}
}

字符流

常见的字符编码

编码方式和解码方式不一样时会出现乱码

  • ISO-8859-1 包括ASCII 西欧 希腊语 泰语 阿拉伯语 希伯来语对应的文字符号(一个字节,只能表示255个字符)

  • UTF-8 万国码(1/2/3个字节表示)

  • GB2312 简体中文(1/2个字节表示)

  • GBK 简体中文,扩充(1/2个字节表示)

  • BIG5 台湾,繁体中文

字符流的父类(抽象类)

  • Reader:字符输入流

    • public int read(){}

    • public int read(char[] c){}

    • public int read(char[] c, int off, int len){}

  • Writer:字符输出流

    • public void write(int n){}

    • public void write(String str){}

    • public void write(char[] c){}

文件字符流

  • FileReader:

    • public int read(char[] c) //从流中读取多个字符,将读到内容存入c数组,返回实际读到的字符数;如果到达文件尾部,则返回-1

public class Demo1 {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("d:\\hello.txt");
//单个字符读取
int data=0;
while ((data=fr.read())!=-1){
System.out.print((char) data);
}
//自建缓存区,一次性读取
char[] buf = new char[1024];
int count = 0;
while ((count= fr.read(buf))!=-1){
System.out.println(new String(buf,0,count));
}
fr.close();
}
}
  • FileWriter:

    • public void write(String str) //一次写入多个字符

public class Demo1 {
public static void main(String[] args) throws Exception {
FileWriter fw = new FileWriter("d:\\hello.txt");
//单个字符读取
for (int i = 0; i < 10; i++) {
fw.write("Java是世界上最好的语言\r\n");
fw.flush();
}
fw.close();
}
}

使用FileReader和FileWriter只能复制文本文件,不能复制图片或者二进制文件

因为图片和二进制文件没有字符编码

字符缓冲流

  • 缓冲流:BufferedReader/BufferedWriter

  • 优点

    • 高效读写

    • 支持输入换行符

    • 可一次写一行,读一行

  • BufferedReader

public class Demo1 {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("d:\\write.txt");
BufferedReader br = new BufferedReader(fr);
//一行一行读
String line = null;
while ((line = br.readLine())!=null){
System.out.println((line);
}
//可以自己创建一个缓存区
char[] buf = new char[1024];
int count = 0;
while ((count = br.read(buf))!=-1){
System.out.println(new String(buf,0,count));
}

br.close();
}
}
  • BufferedWriter

public class Demo1 {
public static void main(String[] args) throws Exception {
FileWriter fw = new FileWriter("d:\\write.txt");
BufferedWriter bw = new BufferedWriter(fw);

for (int i = 0; i < 10; i++) {
bw.write("好好学习,天天向上");
bw.newLine();//写入一个换行符(每个系统的换行符不一样,但这个方法均适配)
bw.flush();
}
bw.close();
}
}

打印流

  • PrintWriter:

    • 封装了print()/println()方法,支持写入后换行

    • 支持数据原样打印

public class Demo1 {
public static void main(String[] args) throws Exception {
PrintWriter pw = new PrintWriter("d:\\print.txt");

pw.println(97);
pw.println(true);
pw.println(3.14);
pw.println('a');

pw.close();
}
}

转换流

  • 桥转换流:InputStreamReader/OutputStreamWriter

    • 可将字节流转换为字符流

    • 可设置字符的编码方式

  • InputStreamReader

public class Demo1 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("d:\\writer.txt");
InputStreamReader irs = new InputStreamReader(fis,"utf-8");

int data = 0;
while ((data = irs.read())!=-1){
System.out.print((char)data);
}

irs.close();
}
}
  • OutputStreamWriter

public class Demo1 {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("d:\\info.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");

for (int i = 0; i < 10; i++) {
osw.write("我爱川农\r\n");
osw.flush();
}

osw.close();
}
}

 

posted @ 2021-11-27 20:43  _SummeRr  阅读(37)  评论(0)    收藏  举报