Java基础——IO流

文章目录

  • IO流概述和分类
    • IO 流介绍
    • IO 流的分类
  • 字节流
    • 字节输出流
    • 字节输入流
    • 字节缓冲流
  • 字符流
    • 概述
    • 编码解码问题
    • 字符输出流
    • 字符输入流
    • 字符缓冲流
  • IO特殊操作流
    • 字节打印流
    • 字符打印流
    • 对象序列化流
    • 对象反序列化流
  • Properties 集合
    • 概述
    • 和IO流结合

IO流概述和分类

IO 流介绍

1.IO :输入/输出(Input/Output)
2.流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流的本质是数据传输
3.IO 流就是用来处理设备间数据传输问题的。常见的应用:文件复制;文件上传;文件下载

IO 流的分类

1.按照数据的流向

  • 输入流:读数据
  • 输出流:写数据

2.按照数据类型来分

  • 字节流
    字节输入流
    字节输出流
  • 字符流
    字符输入流
    字符输出流

3.IO 流的使用场景

  • 如果操作的是纯文本文件,优先使用字符流
  • 如果操作的是图片、视频、音频等二进制文件。优先使用字节流
  • 如果不确定文件类型,优先使用字节流。字节流是万能的流

4.总体分为字节流和字符流,如下所示:
Java基础——IO流_第1张图片

Java基础——IO流_第2张图片

字节流

字节输出流

一、 概述
1.OutputStream :这个抽象类是表示字节输出流的所有类的超类

2.FileOutputStream(String name) :创建文件输出流以指定的名称写入文件,步骤如下

  • 创建字节输出流对象 (调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件)如:FileOutputStream fos = new FileOutputStream(“zy\\java”,true);
  • 调用字节输出流对象的写数据方法
  • 释放资源 (关闭此文件输出流并释放与此流相关联的任何系统资源)

二、 写数据方法

Java基础——IO流_第3张图片如:
//ab
fos.write(“abc”.getBytes(),0,2);

//abc
byte[] bys = “abc”.getBytes();
fos.write(bys);

三、 写数据的两个小问题
1.字节流写数据如何实现换行 windows:\r\n
如:fos.write("\r\n".getBytes());

2.字节流写数据如何实现追加写入

  • public FileOutputStream(String name,boolean append)
  • 创建文件输出流以指定的名称写入文件。如果第二个参数为 true ,则字节将写入文件的末尾而不是开头

四、用try-catch-finally进行异常处理
try {
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}finally{
执行所有清除操作;
}
被 finally控制的语句一定会执行,除非JVM退出

public class FileOutputStreamDemo04 {
  public static void main(String[] args) {
    //加入finally来实现释放资源
    FileOutputStream fos = null;
    try {
      fos = new FileOutputStream("myByteStream\\fos.txt");
      fos.write("hello".getBytes());
   } catch (IOException e) {
      e.printStackTrace();
   } finally {
      if(fos != null) {
        try {
          fos.close();
       } catch (IOException e) {
          e.printStackTrace();
       }
     }
   }
 }
}

jdk7改进方案:

//不用释放资源了,自动释放
try(FileReader fr = new FileReader("fr.txt");
      FileWriter fw = new FileWriter("fw.txt");){
      char[] chs = new char[1024];
      int len;
      while ((len = fr.read()) != -1) {
        fw.write(chs, 0, len);
     }
   } catch (IOException e) {
      e.printStackTrace();
   }

jdk9改进方案

FileReader fr = new FileReader("fr.txt");
    FileWriter fw = new FileWriter("fw.txt");
    try(fr;fw){
      char[] chs = new char[1024];
      int len;
      while ((len = fr.read()) != -1) {
        fw.write(chs, 0, len);
     }
   } catch (IOException e) {
      e.printStackTrace();
   }

字节输入流

一、概述
1.InputStream :这个抽象类是表示字节输入流的所有类的超类

2.FileInputStream(String name) :通过打开与实际文件的连接来创建一个FileInputStream ,该文件由文件系统中的路径名name命名

  • 创建字节输入流对象
  • 调用字节输入流对象的读数据方法
  • 释放资源

二、读数据方法
1.一次读一个字节数据
int by;
while ((by=fis.read())!=-1) {
System.out.print((char)by);
}

2.一次读一个字节数组数据
byte[] bys = new byte[1024]; //1024及其整数倍
int len;
while ((len=fis.read(bys))!=-1) {
System.out.print(new String(bys,0,len));
}

注意:首先需要一个字节数组来存储读到的数据;len的值是读入缓冲区的总字节数 ,也就是实际的读取字节个数!

字节缓冲流

一、 概述
目的:提高效率

  • BufferOutputStream :该类实现缓冲输出流。 通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用
  • BufferedInputStream :创建BufferedInputStream将创建一个内部缓冲区数组。 当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节

二、 构造方法
Java基础——IO流_第4张图片如下:
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(“zy\\视频.avi”));

读写方法和字节输入流、字节输出流一致!

字符流

概述

1.由于字节流操作中文不是特别的方便,所以Java就提供字符流

2.字符流 = 字节流 + 编码表

3.常见中文编码字符集

  • GBK:最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案。
  • UTF-8编码:可以用来表示Unicode标准中任意字符,它是电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。它使用一至四个字节为每个字符编码,大部分常用字(含中文),使用三个字节编码

编码解码问题

一、字符串的编码解码问题:

		String s = "基础";
		
		//编码
        //byte[] bytes = s.getBytes();默认为UTF-8  [-27, -97, -70, -25, -95, -128]
        byte[] bytes = s.getBytes("gbk");
        System.out.println(Arrays.toString(bytes));//[-69, -7, -76, -95]

        //解码
        //String ss = new String(bytes);
        String ss = new String(bytes,"gbk");
        System.out.println(ss);

二、字符流中的编码解码问题:

  • InputStreamReader :是从字节流到字符流的桥梁,它读取字节,并使用指定的编码将其解码为字符(一般默认)
  • OutputStreamWriter :是从字符流到字节流的桥梁,是从字符流到字节流的桥梁,使用指定的编码将写入的字符编码为字节(一般默认)

构造方法:
Java基础——IO流_第5张图片
如下:
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“zy\\hh”));

字符输出流

一、写数据方法

Java基础——IO流_第6张图片
写完要刷新一下,才会写到文件里

字符输入流

一、读数据方法

1.一次读一个字节数据
int ch;
while ((ch=fis.read())!=-1) {
System.out.print((char)ch);
}

2.一次读一个字节数组数据
char[] chs = new char[1024]; //1024及其整数倍
int len;
while ((len=isr.read(chs))!=-1) {
System.out.print(new String(chs,0,len));
}

注意:

  • InputStreamReader为了简化,可用 FileReader替换
    FileReader fr = new FileReader(“myCharStream\\1.java”);
  • OutputStreamWriter 为了简化,可用 FileWriter替换
    FileWriter fw = new FileWriter(“myCharStream\\2.java”);

字符缓冲流

一、概述

  • BufferedWriter :将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。默认值足够大,可用于大多数用途
  • BufferedReader :从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途

二、构造方法
Java基础——IO流_第7张图片
如下:
BufferedWriter bw = new BufferedWriter(new FileWriter(“zy\\copy3.java”));

三、特有方法(最常用)
Java基础——IO流_第8张图片

ublic class BufferStreamDemo2 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("C:\\IntelliJ IDEA 2018.2.2\\project\\day18\\zy\\src\\io\\CopyDemo.java"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("zy\\copy3.java"));

        String line;
        while((line=br.readLine()) != null){
            bw.write(line);
            bw.newLine();//换行
            bw.flush();
        }

        br.close();
        bw.close();
    }
}

IO特殊操作流

字节打印流

PrintStream

特点:

  • 只负责输出数据,不负责读取数据
  • 永远不会抛出 IOException
  • 有自己的特有方法(print,println)

构造方法:
PrintStream ps = new PrintStream(“myOtherStream\\ps.txt”);

字符打印流

PrintWriter

构造方法(第一个不能自动刷新,第二个能):

  • PrintWriter pw = new PrintWriter(“zy\\pw.txt”);

  • PrintWriter pw = new PrintWriter(new FileWriter(“zy\\pw.txt”),true);

对象序列化流

一、概述
1.对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象

2.这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息

3.字节序列写到文件之后,相当于文件中持久保存了一个对象的信息

4.反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化

二、方法
Java基础——IO流_第9张图片
三、注意事项
1.一个对象要想被序列化,该对象所属的类必须必须实现 Serializable 接口

2.Serializable 是一个标记接口,实现该接口,不需要重写任何方法

对象反序列化流

Java基础——IO流_第10张图片

代码示例:

 //反序列化
  private static void read() throws IOException, ClassNotFoundException {
    ObjectInputStream ois = new ObjectInputStream(new
FileInputStream("myOtherStream\\oos.txt"));
    Object obj = ois.readObject();
    Student s = (Student) obj;
    System.out.println(s.getName() + "," + s.getAge());
    ois.close();
 }
  //序列化
  private static void write() throws IOException {
    ObjectOutputStream oos = new ObjectOutputStream(new
FileOutputStream("myOtherStream\\oos.txt"));
    Student s = new Student("林青霞", 30);
    oos.writeObject(s);
    oos.close();
 }
}

注意事项:
1.给对象所属的类加一个 serialVersionUID,
private static final long serialVersionUID = 42L;我们即使修改了对象所属的类文件,读取数据也不会出问题,否则会抛出异常

2.给该类成员变量加 transient关键字修饰,该关键字标记的成员变量不参与序列化过程,那就读不出来

Properties 集合

概述

  • 是一个 Map体系的集合类
  • Properties 可以保存到流中或从流中加载
  • 属性列表中的每个键及其对应的值都是一个字符串

构造方法;
Properties prop = new Properties()
;

Java基础——IO流_第11张图片
特有遍历方法:

Set<String> names = prop.stringPropertyNames();
    for (String key : names) {
      String value = prop.getProperty(key);
      System.out.println(key + "," + value);
   }

和IO流结合

Java基础——IO流_第12张图片

示例代码如下:

	//把文件中的数据加载到集合
	private static void myLoad() throws IOException {
        FileReader fr = new FileReader("zy\\hh.txt");

        Properties pop = new Properties();

        pop.load(fr);

        Set<String> set = pop.stringPropertyNames();
        for(String key : set){
            String value = pop.getProperty(key);
            System.out.println(key+","+value);
        }


        fr.close();
    }

	//把集合中的数据保存到文件
    private static void myStore() throws IOException {
        FileWriter fw = new FileWriter("zy\\hh.txt");

        Properties pop = new Properties();

        pop.setProperty("944","zy");
        pop.setProperty("945","lx");

        pop.store(fw,null);

        fw.close();

    }

你可能感兴趣的:(JavaSE基础)