前言

本文章包括了大部分java IO流的重要知识,是基于韩顺平老师的讲解,十分详细且易懂,主要包括:

  1. 文件
  2. IO流原理及流的分类
  3. 节点流和处理流
  4. 输入流(InputStream,Reader)
  5. 输出流(OutputStream,Writer)
  6. Properties类

文件的基础知识

  • 什么是文件

  • 在这里插入图片描述

    文件,对我们来说并不陌生,文件是保存数据的地方,比如大家用的word文档,txt文件,excel文件。它既可以保存一张图片,也可以保持视频,声音

  • 文件流

    文件在程序中以流的形式来操作的

    流:数据在数据源(文件)和程序(内存)之间经历的路径

    输入流:数据从数据源(文件)到程序(内存)的路径

    输出流:数据从程序(内存)到数据源(文件)的路径
    在这里插入图片描述


创建文件

  • 创建文件对象相关构造器和方法

    1. 相关方法

      - 1. new File(String pathname)//根据路径构建一个File对象
      
           new File(File parent,String child)//根据父目录文件+子路径构建
      
           new File(String parent,String child)//根据父目录+子路径构建
      
           createNewFile//创建新文件
      
      
      
  • 创建文件对象相关构造器和方法

在这里插入图片描述

package IO_file;

import org.junit.jupiter.api.Test;

import java.io.File;
import java.io.IOException;

//创建文件
public class FileCreate {
    public static void main(String[] args) {

    }
    //方式1:new File( String pathname)
    @Test
    public void create01(){
        String filePath ="C:\\news1.txt";
        File file = new File(filePath);
        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Test
    //方式2:new File(File parent,String child)//根据父目录文件+子路径构建
    //c:\\news2.txt
    public void create02(){
        File parentfile = new File("c:\\");
        String childfile ="news.txt";
        //这里file在java程序中只是一个java对象
        //只有执行了createNewFile方法,才会正在地在磁盘创建该文件
        File file = new File(parentfile,childfile);
        try {
            file.createNewFile();
            System.out.println("创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Test
    //方法3:new File(String parent,String child)//根据父目录+子路径构建
    public void create03(){
        String parentpath = "c:\\";
        String childname ="news3.txt";
        File file = new File(parentpath,childname);
        try {
            file.createNewFile();
            System.out.println("创建成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }


    }
}


目录操作

常见地文件操作

  • 目录的操作和文件删除

    mkdir创建一级目录,mkdirs创建多级目录,delete删除空目录或文件

  • 案例演示

    1. //判断 c:\news1.txt 是否存在,如果存在就删除
    2. //判断 c:\demo02目录是否存在,存在就删除,否则就提示不存在
    3. //判断 c:\demo\a\b\c 目录是否存在,如果存在就提示存在,否则就创建
package IO_file;

import org.junit.jupiter.api.Test;

import java.io.File;

public class Directory_ {
    public static void main(String[] args) {
        //

    }
    //判断 c:\\news1.txt  是否存在,如果存在就删除
    @Test
    public void m1(){
        String filePath = "c:\\news1.txt";
        File file = new File(filePath);
        if(file.exists()){
            if(file.delete()){
                System.out.println(filePath+"删除成功");
            }
            else{
                System.out.println(filePath+"删除失败");
            }
        }else{
            System.out.println("该文件不存在...");
        }
    }
    //判断 c:\\demo02目录是否存在,存在就删除,否则就提示不存在
    //这里我们需要体会到,在java编程中,目录也被当成文件
    @Test
    public void m2(){
        String filePath = "c:\\demo02";
        File file = new File(filePath);
        if(file.exists()){
            if(file.delete()){
                System.out.println(filePath+"删除成功");
            }
            else{
                System.out.println(filePath+"删除失败");
            }
        }else{
            System.out.println("该文件不存在...");
        }
    }
    //判断 c:\\demo\\a\\b\\c 目录是否存在,如果存在就提示存在,否则就创建
    @Test
    public void m3(){
        String directionPath = "c:\\demo\\a\\b\\c";
        File file = new File(directionPath);
        if(file.exists()) {
            System.out.println(directionPath+"该目录已经存在");
        }
            else{
                if(file.mkdirs()) {//创建一级目录用mkdir(),创建多久目录用mkdirs();
                    System.out.println(directionPath+"创建成功");
                }
                else
                    System.out.println(directionPath+"创建失败");
            }
    }
}



IO流原理和分类

  • Java IO流原理

    1. I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理数据传输。如读/写文件,网络通讯等。

    2. Java程序中,对于数据的输入/输出操作以"流(stream)"的方式进行。

    3. java.io包下提供了各种"流"类和接口,用以获取不同种类的数据,并通过方法输入或输出数据

    4. 输入input:读取外部数据(磁盘,光盘等存储设备的数据)到程序(内存)中。

    5. 输出output:将程序(内存)数据输出到磁盘,光盘等存储设备中

  • 流的分类

    1. 按操作数据单位不同分为:字节流(8 bit),字符流(按字符)

    2. 按数据流的流向不同分为:输入流,输出流

    3. 按流的角色的不同分为:节点流,处理流/包装流

      抽象基类 字节流 字符流
      输入流 InputStream Reader
      输出流 OutputStream Writer
      • java中IO流共涉及40多个类,实际上非常规则,都是从如上4个抽象基类派生的。
      • 由这4个类派生出来的子类名称都是以其父类名为子类名后缀
  • IO流体系图-常用的类

    1. IO流体系图
    2. 文件VS流

在这里插入图片描述

FileInputStream (字节输入流)

IO流体系图-常用的类

  • InputStream抽象类是所有类字节输入流的超类
  • InputStream常用的子类
    1. FileInputStream:文件输入流
    2. BufferedInputStream:缓存字节输入流
    3. ObjectInputStream:对象字节输入流
      在这里插入图片描述
  • FileInputStream介绍
  • FileInputStream应用实例
    1. 创建FileInputStream对象,用read()方法读取文件数据
/*
    *单个字节读取,效率低
    * ->使用read()
     */

    @Test
    public void readFile01(){
        String filePath = "c:\\hello.txt";
        int readData=0;
        FileInputStream fileInputStream=null;
        try {
            //创建fileInputStream对象,用于读取文件
           fileInputStream  = new FileInputStream(filePath);
            //从该输入流读取一个字节的数据。如果没有输入可用,此方法将阻止
            //如果返回-1,表示读取完毕
       while((readData=fileInputStream.read())!=-1){
           System.out.print((char)readData); //打印是int转换为char显示
            }                                                               //若打印汉字会出现乱码,一个汉字三个字节,而这是一个字节一个字节打印
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭文件流,释放资源
            try {
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
  1. 创建FileInputStream对象,用read(byte[] b)方法读取文件

     /*
        *使用read(byte[] b)
         */
        @Test
        public void readFile02(){
            String filePath = "c:\\hello.txt";
            int readLen=0;
            //字节数组
            byte[] buf = new byte[8];//一次读8个字节
            FileInputStream fileInputStream=null;
            try {
                //创建fileInputStream对象,用于读取文件
                fileInputStream  = new FileInputStream(filePath);
                //从该输入流读取最多b,length字节的数据到字节数组。此方法将阻塞,直到某些输入可用
                //如果返回-1,表示读取完毕
                //如果读取正常,返回实际读取的字节数
                while((readLen=fileInputStream.read(buf))!=-1){
                    System.out.print(new String(buf,0, readLen)); //打印是int转换为String显示
                }                                                               //若打印汉字会出现乱码,一个汉字三个字节,而这是一个字节一个字节打印
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                //关闭文件流,释放资源
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    

FileOutputStream(字节输出流)

IO流体系图-常用的类
在这里插入图片描述

  • FileOutputStream应用实例

    要求:请使用FileOutStream在a.txt文件,中写入"hello,world",如果文件不存在,会创建文件

    演示使用FileOutStream 将数据写到文件中
    
    public class FileOutputStream01 {
        public static void main(String[] args) {
    
        }
        @Test
        /*
        * 演示使用FileOutStream 将数据写到文件中
        * 如果文件不存在,则创建该文件
         */
        public  void  writeFile(){
            //创建FileOutStream对象
            //说明
            //1.new FileOutputStream(filePath)创建方式,当写入内容是,会覆盖原来内容
            //2.new FileOutputStream(filePath,true)创建方式,当写入内容是,是追加到文件后面
            String filePath="c:\\a.txt";
            FileOutputStream fileOutputStream = null;
            try {
                //得到FileOutputStream对象
                fileOutputStream = new FileOutputStream(filePath,true);
                //写人一个字节
               // fileOutputStream.write('a');
                //写入字符串
                String str ="hello world";
                //str.getBytes()可以把字符串->字节数组
               // fileOutputStream.write(str.getBytes());
                /*
                write(byte[]b, int off,int len)将len字节从位于偏移量off的指定数组
                 */
                fileOutputStream.write(str.getBytes(),0,3);
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    

文件拷贝

  • 实例分析

    将c:\JAVA.jpg拷贝到C:\web\JAVA.jpg

    分析:我们需要将该JAVA.jpg文件先输入到程序,然后在从程序中输出到磁盘中,包含FileInputStream,和FileInputStream使用

package IO_Outputstream;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileCopy {
    public static void main(String[] args) {
        //完成文件拷贝,将c:\JAVA.jpg拷贝到C:\web\JAVA.jpg
        //思路分析
        //1. 创建文件的输入流,将文件读入到程序
        //2. 创建文件的输出流,将读到的文件数据,写入到指定的文件
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        String srcFilePath = "c:\\JAVA.jpg";//定义输出路径
        String destFilePath="C:\\web\\JAVA.jpg";//定义输入路径
        try {
            fileInputStream = new FileInputStream(srcFilePath);
            fileOutputStream= new FileOutputStream(destFilePath);
            //定义一个字节数组,提高读取效果
            byte[] buf = new byte[1024];
            int readlen=0;
            while((readlen=fileInputStream.read(buf))!=-1)
            {
                //读取到后,就写入到文件  通过fileOutputStream
                //即,一边读,一边写
                fileOutputStream.write(buf,0,readlen);//一定要用这个方法,提高输出速度
            }
            System.out.println("拷贝成功");
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            //关闭输出流和输入流
            if(fileInputStream!=null){
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if ((fileOutputStream!=null)){
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}


文件字符流说明

  • FileReader和FileWriter介绍

    FileReader和FileWriter是字符输入流,即字符来操作io

  • FileReader相关方法:

    1. new FileReader(File/String)
    2. read:每次读取单个字符,返回该字符,如果到文件末尾返回-1
    3. read(char[]):批量读取多个字符到数组,返回读取到字符数,如果到文件末尾返回-1
  • 相关API

    1. new String(char[]):将char[]转换成String
    2. new String(char[],off,len):将char[]的指定部分转换成String

  • FileWriter常用方法

    1. new FileWriter(File/String):覆盖模式,相当于流的指针在首端
    2. new FileWriter(File/String,true):追加模式,相当于流的指针在尾端
    3. write(int):写人单个字符
    4. write(char[]):写入指定数组
    5. write(char[],off,len):写入指定数组的指定部分
    6. write(String):写入整个字符串
    7. write(String,off,len):写入指定字符串的指定部分
    8. 相关 API: String类:toCharArray:将String转换为char[]
  • 注意:

    FileWriter使用后,必须关闭(close)或刷新(flush),否则写入不到指定文件


    FileReader

    • FileReader和FileWriter

      要求:

      1. 使用FileReader从story.txt读取内容,并显示
        • 方法1,单个字符读取,用read()
 /*
    *单个字符读取文件
     */
    @Test
    public  void readFile01(){
        System.out.println("第二种");
        String filePath="c:\\story.txt";
        // 1.创建FileReader对象
        FileReader fileReader = null;
        int data=' ';
        try {
            fileReader = new FileReader(filePath);
            //循环读取  使用read,单个字符读取
            while((data=fileReader.read())!=-1){
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fileReader!=null){
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
  • 方法2,使用字符数组读取文件 read(buf)

     /*
         *字符数组读取文件
         */
        @Test
        public  void readFile02(){
            String filePath="c:\\story.txt";
            // 1.创建FileReader对象
            FileReader fileReader = null;
            int readLen = 0;
            char[] buf = new char[8];
            try {
                fileReader = new FileReader(filePath);
                //循环读取  使用read,单个字符读取
                while((readLen=fileReader.read(buf))!=-1){
                    System.out.print(new String(buf,0,readLen));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if (fileReader!=null){
                    try {
                        fileReader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    

    FileWriter

    • 案例:使用FileWriter将"风雨之后,定见彩虹"写入note.txt文件中,注意细节

      package I0_Writer;
      
      import java.io.FileWriter;
      import java.io.IOException;
      
      public class FileWriter_ {
          public static void main(String[] args) {
              String FilePath="c:\\note.txt";
              //创建FileWriter对象
              FileWriter filewriter = null;
              char[] chars = {'a','b','c'};
              try {
                  filewriter = new FileWriter(FilePath);
      //            1. write(int):写人单个字符
                  filewriter.write('H');
      //            2. write(char[]):写入指定数组
                  filewriter.write(chars);
      //            3. write(char[],off,len):写入指定数组的指定部分
                  filewriter.write("琳琳我".toCharArray(),0,3);
      //            4. write(String):写入整个字符串
                  filewriter.write("风雨之后见彩虹");
                  filewriter.write("  你好北京");
      //            5. write(String,off,len):写入指定字符串的指定部分
                  filewriter.write("上海北京",0,2);
                  //在数据量大的情况下,用循环操作
              } catch (IOException e) {
                  e.printStackTrace();
              }finally{
                  //对于FileWriter,一定要关闭流,或者flush才能正在的把数据写入到文件
                  try {
                     // filewriter.flush();
                      //close等于fulsh()+关闭
                      filewriter.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }
      }
      
      

节点流处理流

  • 基本介绍

    1. 节点流可以从一个特定的数据源读写数据,如FileReader,FileWriter, 固定的,灵活性不足
      • 文件—>程序(通过节点流)
    2. 处理流也叫包装流,是"连接"在已存在的流(节点流或处理流)之上,为程序提供更强大的读写功能,如BufferedReader,BufferedWriter 可以对节点流进行包装,也更加灵活,可以是文件,也可以是其他数据源
  • 节点流和处理流一览图

  • BufferedReader/BufferedWriter

    1. BufferReader类中,有属性Reader,即可以封装一个节点流,该节点流可以是任意的,只要是Reader子类
    2. BufferWriter类中和BufferReader类似。

处理流设计模型

  • 节点流和处理流的区别和联系
    1. 节点流是底层流,低级流,直接跟数据源相接
    2. 处理流(包装流)包装节点流,即可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出(源码理解)
    3. 处理流也叫包装流对节点流进行包装,使用了修饰器设计模式不会直接与数据源相连(模拟修饰器设计模式)
  • 处理流的功能主要体现在以下两个方面
    1. 性能的提高:主要以增加缓冲的方式来提高输入输出的效率
    2. 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便

BufferedReader

在这里插入图片描述

  • 处理流-BufferedReader和BufferedWriter
    1. BufferedReader和BufferedWriter属于字符流,是按照字符来读取数据的(最好用文本文件)
    2. 关闭处理流,只需要关闭外层节点流
  • 应用案例
    1. 使用BufferedReader读取文本文件,并显示在控制台
package IO_reader;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

/*
演示bufferedreader应用
 */
public class BufferedReader_ {
    public static void main(String[] args) throws IOException {
        String filePath="c:\\ab.txt";
        //创建bufferedReader
        BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
        //读取
        String line;//按行读取,效率高
        //说明
        //1.bufferedReader.readLine() 是按行读取文件
        //2.当返回null时,表示文件读取完毕
        while((line=bufferedReader.readLine())!=null){
            System.out.println(line);
        }
        //关闭流,这里注意,只需要关闭BufferedReader,因为底层会自动的去关闭节点流
        bufferedReader.close();
    }
}


BufferedWriter

  • 应用案例
    2. 使用BufferedWriter 将"hello,xxx"写入到文件中
public class BufferedWrite1 {

	public static void main(String[] args)	throws IOException {
		// TODO Auto-generated method stub
		String filePath="e:\\ok.txt";
		//创建BufferWritered
        //说明
        //1. new FileWriter(filePath,true) 表示以追加的方式写人
        //2.new FileWriter(filePath) 表示以覆盖的方式写入
		new BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
		//new BufferedWriter
		bufferedWriter.write("hello, 韩顺的");
        bufferedWriter.newLine();//插入一个和系统相关的换行
        bufferedWriter.write("hello, 韩顺的");
        bufferedWriter.newLine();//插入一个和系统相关的换行
        bufferedWriter.write("hello, 韩顺的");
        //说明:关闭外层流即可,传入的 new FileWriter(filePath),会在底层流关闭
        bufferedWriter.close(); 
	}

}


Buffered拷贝

  • 应用案例
  1. 综合使用BufferedReader和BufferedWriter完成文本文件的拷贝

    public class BufferedCopy_(){
        public static void main(String[] args){
            //说明
            //1.BufferedReader 和BufferedWriter 是按照字符读取
             //2.不要用去操作二进制文件,可能造成文件损失
            String srcFilePath = "e:\\a.java";
            String destFilePath = "e:\\a2.java";
            BufferedReader br = null;
            BufferedWriter bw = null;
            String line;
            try{
                br = new BufferedReader(new FileReader(srcFilePath));
                bw = new BufferedWriter(new FileWriter(destFilePath));
                //说明:readLine  读取一行内容,但是没有换行
                while((line = br.readLine())! = null){
                    //没读取一行就写入
                    bw.write(line);
                    //插入一个换行
                    bw.newLine();
                }
                System.out.println("拷贝完成");
                
                
            } catch(IOException e){
                e.printStackTrace();
            } finally{
                //关闭流
                try{
                if(br!=null){
                    br.close();
                }
                if(bw!=null){
                    bw.close();
                }
                }catch(IOExcption e){
                    e.printStackTrace();
                }
            }
            
         
        }
    }
    

    Buffed字节处理流

    • 处理流-BufferedInputStream和BufferedOutputStream
      1. BufferedOutputStream是字节流,实现缓冲的输出流,可以将多个字节写入底层输出流中,而不必对每次字节写入调用底层系统
      2. BufferedInputStream是字节流,在创建BufferedInputStream时,会创建一个内部缓冲区数组

    字节处理流拷贝文件

    • 应用案例

      1. 要求编写完成图片,音乐的拷贝,使用Buffered…流(图片音乐是二进制)
      package IO_Outputstream;
      import java.io.*;
      /*
      演示BufferedOutputStream和BufferedOutputStream
      字节流使用他们可以完成二进制文件拷贝
      也可以操作文本文件
       */
      public class BufferedCopy02 {
          public static void main(String[] args) {
              String srcFilePath="c:\\JAVA.jpg";
              String destFilePath="c:\\web\\wen.jpg";
              //创建BufferedOutputStream对象和BufferedInputStream对象
              BufferedInputStream bis = null;
              BufferedOutputStream bos = null;
              try {
                  //因为FileInputStream是InputStream的子类
                  bos= new BufferedOutputStream(new FileOutputStream(destFilePath));
                  bis=new BufferedInputStream(new FileInputStream(srcFilePath));
                 //循环读取文件,并写入到destFilePath
                  byte[] bytes = new byte[1024];
                  int len = 0;
                  while ((len= bis.read(bytes))!=-1){
                      bos.write(bytes,0,len);
                  }
                  System.out.println("拷贝成功");
              } catch (IOException e) {
                  e.printStackTrace();
              }finally{
                  //关闭流,关闭外层流
                  if(bis!=null){
                      try {
                          bis.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
                  if(bos!=null){
                      try {
                          bos.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
      
          }
      }
      
      

对象处理流

  • 对象流-ObjectInputStream和ObjectOutputStream (仍然是处理流)

    • 看一个需求
    1. 将int num = 100 这个 int 数据保存到文件中,注意不是100数字,而是int 100,并且,能够从文件中直接恢复int 100
    2. 将Dog dog = new Dog(“小黄”,3)这个dog对象保存到文件中,并且能够从文件中恢复
    3. 上面的要求,就是能够将基本数据类型或者对象进行序列化和反序列化操作
    • 序列化和反序列化
    1. 序列化就是保存数据时,保存数据的值和数据类型
    2. 反序列化就是恢复数据时,恢复数据的值和数据类型
    3. 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
      1. Serializable //标记接口,推荐!!,里面无任何方法
      2. Externalizable //该接口有方法需要实现,推荐使用Seralizable接口
  • 基本介绍

    1. 功能:提供了对基本类型或者对象类型的序列化和反序列化的方法
    2. ObjectOutputStream提供序列化功能
    3. ObjectInputStream提供反序列功能

在这里插入图片描述


ObjectOutputStream

在这里插入图片描述

  • 应用案例
  1. 使用ObjectOutputStream序列化基本数据类型和一个Dog对象(name,age),并保存到data.dat

    package IO_Inputstream;
    
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    
    /*
    演示ObjectOutputStream的使用,完成数据的序列化
     */
    public class ObjectOutputStream_ {
        public static void main(String[] args) throws IOException {
            //序列化后,保存的文件格式,不是纯文本而是按照他的格式来保存
            String filePath="c:\\data.dat";
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
            //序列化数据到c:\\data.dat
            oos.write(100);//int->Integer(实现了Serialzable)
            oos.writeBoolean(true);//boolean->Boolean(实现了Serialzable)
            oos.writeChar('a');//char->Character  (实现了Serialzable)
            oos.writeDouble(9.5);//double->Double(实现了Serialzable)
            oos.writeUTF("xxx");//String(实现了Serialzable)
            //保存一个dog对象
            oos.writeObject(new dog("旺财",12));
            oos.close();
            System.out.println("数据保存完毕序列化形式");
        }
    
    }
    class dog implements Serializable {
        private String name;
        private int age;
    
        public dog(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }
    
    
    

    ObjectInputStream

    • 应用案例

      1. 使用ObjectInputStream读取data.dat并反序列化恢复数据
      package IO_Inputstream;
      import IO_Outputstream.dog;
      
      import java.io.FileInputStream;
      import java.io.IOException;
      import java.io.ObjectInputStream;
      
      public class ObjectInputStream_ {
          public static void main(String[] args) throws IOException, ClassNotFoundException {
              //序列化后,保存的文件格式,不是纯文本而是按照他的格式来保存
              String filePath="c:\\data.dat";
              ObjectInputStream  ois = new ObjectInputStream(new FileInputStream(filePath));
              //读取
              //1.读取反序列化的顺序需要和你保存数据序列化的顺序一致
              //2.否则会出现异常
              System.out.println(ois.readInt());
              System.out.println(ois.readBoolean());
              System.out.println(ois.readChar());
              System.out.println(ois.readDouble());
              System.out.println(ois.readUTF());
              Object dog = ois.readObject();
              System.out.println(dog.getClass());
              System.out.println(dog);//底层object->Dog
              //特别重要的细节
              //1.如果我们希望调用Dog的方法,需要向下转型
              //2.需要我们将Dog类的定义,拷贝到可以引用的位置
              dog dog2 = (dog) dog;
              System.out.println(dog2.getName());
      
      
              //关闭流,关闭外层流即可
              ois.close();
          }
      }
      
      

      dog类

      package IO_Outputstream;
      
      import java.io.Serializable;
      
      public class dog implements Serializable {
          private String name;
          private int age;
      
          public dog(String name, int age) {
              this.name = name;
              this.age = age;
          }
      
          public String getName() {
              return name;
          }
      
          public int getAge() {
              return age;
          }
      
          @Override
          public String toString() {
              return "dog{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      '}';
          }
      }
      
      

对象处理流使用细节

  • 注意事项和细节说明
    1. 读写顺序要一致
    2. 要求实现序列化或反序列化对象,需要实现Serializable
    3. 序列化的类中建议添加SerialVersionUID,为了提高版本兼容性
    4. 序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员
    5. 序列化对象时,要求里面属性的类型也需要实现序列化接口
    6. 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也默认实现了序列化

标准输入输出流

  • 标准输入输出流

    • 介绍
    类型 默认设备
    System.in InputStream 键盘
    System.out PrintStream 显示器
package standard;

public class InputAndOutput {
    public static void main(String[] args) {
        //System类的public final static InputStream in = null;
        //System.in 编译类型 InputStream
        //System.in 运行类型 BufferedInputStream
        //表示的是标准输入  键盘
        System.out.println(System.in.getClass());


        //1.System.out public final static Printstream out = null;
        //2.编译类型 PrintStream
        //3.运行类型PrintStream
        //4.表示标准输出  显示器
        System.out.println(System.out.getClass());
    }
}


乱码引出转换流

  • 转换流-InputStreamReader和OutputStreamWriter
    • 先看一个文件乱码,引出学习转换流必要性
package transformation;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class CodeQuestion {
    public static void main(String[] args) throws IOException {
        //1.创建字符输入流BufferedReader[处理流]
        //2使用BufferedReader 对象读取a.txt
        //3.默认情况下,读取文件是按照utf-8编码
        String filePath = "c:\\a.txt";
        BufferedReader br = new BufferedReader(new FileReader(filePath));
        String s = br.readLine();
        System.out.println("读取到的内容:"+s);
        br.close();
    }
}

如果将a.txt转换为ANSI,则会出现乱码


InputStreamReader

  • 转换流-InputStreamReader和OutputStreamWriter

    • 介绍
      1. InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成Reader(字符流)
      2. OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)包装成Writer(字符流)
      3. 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换为字符流
      4. 可以再使用时指定编码格式比如(utf-8,gbk,gb2312,ISO8859-1等)
  • 应用案例

    1. 编码将字节流FileInputStream包装成字符流InputStreamReader,对文件进行读取按照utf-8格式,进而在包装成BufferedReader
    package transformation;
    
    import java.io.*;
    
    /*
    *演示使用InputStreamReader 转换流解决中文乱码问题
    * 将字节流FileInputStream 转换成字符流InputStreamReader,指定编码gbk/utf-8
     */
    public class InputStreamReader_ {
        public static void main(String[] args) throws IOException {
            String filePath="c:\\a.txt";
            //1.把FileInputStream转成 InputStreamReader
            //InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath),"gbk");
            //3.把InputStreamReader传入BufferedReader
            //BufferedReader br = new BufferedReader(isr);
            //将2和3合在一起
            BufferedReader br = new BufferedReader(new InputStreamReader
                                                   new  FileInputStream(filePath),"gbk"));
            //4.读取
            String s = br.readLine();
            System.out.println("读取内容="+s);
            //5.关闭外层流
            br.close();
        }
    }
    
    

OutputStreamWriter

  • 应用案例

    1. 编程将字节流FileOutputStream包装成字符流OutputStreamWriter,对文件进行写入按照gbk
    package transformation;
    
    import java.io.*;
    
    public class OutputStreamWriter_ {
        public static void main(String[] args) throws IOException {
            String filePath="c:\\a.txt";
            String charset="gbk";
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath),charset);
            osw.write("问进ie");
            osw.close();
            System.out.println("按照"+charset+"保存文件成功");
        }
    }
    
    

PrintStream

  • 打印流 PrintStream(字节流)和PrintWriter(字符流)

    • 应用实例,打印流只有输出流,没有输入流
    /*
    PrintStream是字节打印流/输出流
     */
    
    
    
    package PrintStream_;
    
    import java.io.IOException;
    import java.io.PrintStream;
    
    public class PrintStream01 {
        public static void main(String[] args) throws IOException {
            PrintStream out =  System.out;
            //默认情况下,PrintStream输出数据的位置是标准输出,即显示器
            out.print("john,hello");
            out.write("问进杰".getBytes());
            out.close();
            //我们可以去修改打印流输出的位置/设备
            //1.输出修改成到"c:\\f1.txt";
            //2."hello,阿松大就会输出到c:\\f1.txt"
            System.setOut(new PrintStream("c:\\f1.txt"));
            System.out.println("hello,阿松大");
        }
    }
    
    

    PrintWriter

    package PrintStream_;
    
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    public class PrintWriter_ {
        public static void main(String[] args) throws IOException {
            PrintWriter printWriter = new PrintWriter(new FileWriter("c:\\f2.txt"));
            printWriter.print("hi 北京");
            printWriter.close();//flush+关闭流,才会将数据写入到文件
        }
    }
    
    

配置文件引出Properties

  1. Properties类

    • 看一个需求

    如下一个配置文件mysql.properties

    ip=192.168.0.13

    user=root

    pwd=12345

    请问编程读取ip,user和pwd的值是多少

    • 分析
      1. 传统方法
      2. 使用Properties类可以方便实现
  2. 传统方法

    package properties;
    
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    
    public class Properties01 {
        public static void main(String[] args) throws IOException {
        //读取mysql.properties文件,并且得到ip,user和pwd
            BufferedReader br= new BufferedReader(new FileReader("src\\mysql.properties"));
            String line ="";
            while((line=br.readLine())!=null){//循环读取
                String[] splits = line.split("=");
                System.out.println(splits[0]+"值是"+splits[1]);
            }///
            br.close();
        }
    }
    
    
  • 基本介绍

    1. 专门用于读写配置文件的集合类

      配置文件的格式:

      键=值

      键=值

    2. 注意:键值对不需要空格,值不需要用引号引起来。默认类型是String

    3. Properties的常用方法

      1. load:加载配置文件的键值对到Properties对象
      2. list:将数据显示到指定设备
      3. getProperty(key):根据键获取值
      4. setProperty(key,value):设置键值对到Properties对象
      5. store:将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果含有中文,会存储为unicode码
        在这里插入图片描述
  • 应用案例

  1. 使用Properties类完成对mysql.properties的读取

    package properties;
    
    import java.io.FileReader;
    import java.io.IOException;
    import java.util.Properties;
    
    public class Properties02 {
        public static void main(String[] args) throws IOException {
            //使用Properties类来读取mysql.properties 文件
            //1.创建Properties对象
            Properties properties = new Properties();
            //2.加载指定配置文件
            properties.load(new FileReader("src\\mysql.properties"));
            //3.把k-v显示控制台
            properties.list(System.out);
            //4.根据key获取对应的值
            String user = properties.getProperty("user");
            String pwd = properties.getProperty("pwd");
            System.out.println("用户名="+user);
            System.out.println("密码是="+pwd);
            
        }
    }
    
    
  2. 使用Properties类添加key-val到新文件mysql2.properties中

package properties;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class Properties03 {
    public static void main(String[] args) throws IOException {
        //使用Properties类来创建配置文件,修改配置文件内容
        Properties properties = new Properties();
        //创建
        properties.setProperty("charset","utf8");
        properties.setProperty("user","汤姆");//保存是中文的unicode码值
        properties.setProperty("pwd","abc111");
        //将k-v存储文件中即可
        properties.store(new FileOutputStream("src\\mysql2.properties"),null);
        System.out.println("保存配置成功");

    }
}

  1. 使用Properties类完成对mysql.properties的读取,并修改某个key-val
package properties;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class Properties03 {
    public static void main(String[] args) throws IOException {
        //使用Properties类来创建配置文件,修改配置文件内容
        Properties properties = new Properties();
        //创建
        //1.如果该文件没有key就是创建
        //2.如果该文件有key就是修改替换
        properties.setProperty("charset","utf8");
        properties.setProperty("user","汤姆");//保存是中文的unicode码值
        properties.setProperty("pwd","88888");//修改密码
        //将k-v存储文件中即可
        properties.store(new FileOutputStream("src\\mysql2.properties"),null);
        System.out.println("保存配置成功");

    }
}

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐