java学习——IO流

目录

1.文件基础知识

1.常用概念

1.什么是文件 

2.文件流

 2.常用的文件操作

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

1.相关方法

 2.代码:

2.获取文件相关信息

1.常用方法

 2.代码:

3.目录的创建和文件删除 

1.方法

2.代码:

2.IO流和流的分类 

1.Java IO流原理

2.流的分类

3.InputStream:字节输入流

常用的子类介绍:

FIleInputStream类 

1.FileInputStream介绍:

2.代码:

4.OutputStream:字节输出流

常用的子类介绍:

FIleOutputStream类

1.FileOutputStream介绍

5.文件的拷贝

分析:

代码:

 6.FileReader和FileWriter介绍

1.FileReader类

2.FileWriter类

7.节点流和处理流

1.基本介绍:

2.区别和联系

3.功能区别:

 4.模拟底层代码理解:

模拟Reader

模拟节点流:

模拟处理流:

案例:

运行结果:

8.BufferedReader和BuffereredWriter类

1.BufferedReader类

代码: 

2.BufferedWriter类

​编辑

代码:

 9.BufferedInputStream和BufferedOutputStream类

1.BufferedInputStream类

2.BufferedOutputStream类

10.对象流

 1.基本介绍:

2.代码

11.转换流 

 1.InputStreamReade类

 2.OutputStreamWriter类

12.打印流 

1.PrintStream类

2. PrintWriter类

 13.Properties类

 1.基本介绍:

2.代码 


1.文件基础知识

1.常用概念

1.什么是文件 

  • 文件就是保存数据的地方。

2.文件流

  • 文件在程序是以流的形式来操作的 
  • 流数据在数据源(文件)和程序(内存)之间经历的路径
  • 输入流:数据从数据源(文件)到程序(内存)的路径
  • 输出流:数据从程序(内存)到数据源(文件)的路径

 2.常用的文件操作

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

1.相关方法

new File(String pathname)//根据路径构建一个File对象

new File(File parent,String child)//根据父目录文件+子路径构建

new File(String parent,String child)//根据父目录+子路径构建

createNewFile创建新文件 

 2.代码:
import org.junit.jupiter.api.Test;

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

//演示创建文件
public class File_Create {
    public static void main(String[] args) {
        //方式1


    }
    @Test
    public void create01() {
        String filePath="e:\\new.txt";
        File file = new File(filePath);
        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Test
    public void create02(){
        File file = new File("e:\\");
        String filePath="news2.txt";
        File file1 = new File(file, filePath);

        try {
            file1.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Test
    public void create03(){
        String parentPath="e:\\";
        String filePath="news3.txt";
        File file = new File(parentPath, filePath);
        try {
            file.createNewFile();
            System.out.println("创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

结果:

通过代码我们不难发现,我们在代码中new了一个file对象。但我们new了一个file对象是在程序内存 里,也就是说我们在new的时候并不会对磁盘进行操作。需要调用createFile()方法

2.获取文件相关信息

1.常用方法
  • getName//文件名字
  • getAbsolutePath//绝对路径
  • getParent//父级目录
  • length//大小
  • exists//是否存在
  • isFile//是否是文件
  • isDirectory//是否是目录
 2.代码:
    @Test
public void info(){
        
    File file = new File("e:\\new.txt");
    //调用相应的方法    
    System.out.println("文件名字="+file.getName());
        
    System.out.println("绝对路径="+file.getAbsolutePath());
        
    System.out.println("文件父级目录="+file.getParent());
        
    System.out.println("文件大小="+file.length());
        
    System.out.println("是否是文件:"+file.isFile());
        
    System.out.println("是否是存在:"+file.exists());
        
    System.out.println("是不是目录:"+file.isDirectory());
        
}

 结果:

3.目录的创建和文件删除 

1.方法
  • mkdir()创建一级目录
  • mkdirs()创建多级目录
  • delete删除空目录或文件
2.代码:
    @Test
    public void mi(){
        String filePath="e:\\new.txt";
        File file = new File(filePath);
        if (file.exists()){
            if (file.delete()){
                System.out.println("删除成功");
            } else  {
                System.out.println("删除失败");
            }
        }else {
            System.out.println("该文件不存在");
        }
    }
    //判断目录是否存在,存在就删除
    //在Java编程中目录也被当成文件
    @Test
    public void m2(){
        String filePath="e:\\yd";
        File file = new File(filePath);
        if (file.exists()){
            if (file.delete()){
                System.out.println("删除成功");
            } else  {
                System.out.println("删除失败");
            }
        }else {
            System.out.println("该文件不存在");
        }

    }
    @Test
    public void m3(){
        String directoryPath="e:\\yd\\a\\b\\c";
        File file = new File(directoryPath);
        if (file.exists()){
            System.out.println("该目录已经存在");
        }else {
            if (file.mkdirs()){
                System.out.println("该目录创建成功");
            }
            else {
                System.out.println("创建失败");
            }
        }

    }

 我们可以得到,目录也就是我们所说的文件夹在io操作中和文件是一个状态,

2.IO流和流的分类 

1.Java IO流原理

  1. I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理数据传输。如读/写文件,网络通讯等
  2. Java程序中,对于数据的输入/输出操作以“流(stream)”的方式进行
  3. java.io包提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法输出或输入数据。
  4. 输入input:读取外部数据(磁盘,光盘等储存设备的数据)到程序(内存)中。
  5. 输入output:将程序(内存)的数据输出到磁盘,光盘等储存设备中。

2.流的分类

  • 按操作数据单位不同分为:字节流(8bit)二进制文件,字符流(按字符)文本文件

  • 按数据流的流向分为:输入流,输出流

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

  • (抽象基类)字节流字符流
    输入流InputStreamReader
    输出流OutputStreamWriter

  1. Java的IO流共涉及40多个子类,实际上非常规则,都是从如上四个抽象基类派生的
  2.  由这四个类派生出来的子类名称都是以其父类名作为子类名后缀

 

 (图片来自b站网络)

输出流,输入流与数据的关系可以类似于,I/O流是输出输入数据的工具或者方式。好像外卖和外卖员的关系。

3.InputStream:字节输入流

InputStream抽象类是所有类字节输入流的子类

常用的子类介绍:

  1. FileInputStream:文件输入流
  2. BufferedInputStream:缓冲字节输入流
  3. ObjectInputStream:对象字节输入流

 (类的继承关系)

FIleInputStream类 

1.FileInputStream介绍:
构造方法摘要:

FileInputStream(File file)

通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的File对象file指定

FileInputStream(FileDescriptor fdObj)

通过使用文件描述符fdObj创建一个FileInputStream,该文件描述符表示到文件系统中的某个实际文件的现有连接。

FileInputStream(String name)

通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统的路径名name指定

我们可以这么理解:当你的磁盘中存在一个文件的时候,我们创建一个流对象和这个文件联系,并操作这个对象来改变文件。 

方法摘要:

public int available()

返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。

public void close()

关闭此文件输入流并释放与此流有关的所有系统资源。

protected void finalize()

确保在不再引用文件输入流时调用其close 方法。

public FileChannel getChannel()

返回与此文件输入流有关的唯一FileChannel 对象。

public final FileDescriptor getFD()

返回表示到文件系统中实际文件的连接的FileDescriptor 对象,该文件系统正被此 FileInput Strean 使用

public int read()

从此输入流中读取一个数据字节。

public int read(byte b[])

从此输入流中将最多 b.length 个字节的数据读入一个byte 数组中。

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

从此输入流中将最多 len个字节的数据读入一个byte 数组中。

public long skip(long n)

从输入流中跳过并丢弃n个字节的数据。

2.代码:

读取文件:

//读取文件
    @Test
    public void readFile01() throws IOException {
        String filePath="e:\\news2.txt";
        int read_data=0;
        FileInputStream fileInputStream=null;
        try {
            //创建FileInputStream对象
            fileInputStream = new FileInputStream(filePath);
            //如果返回-1表示读取完毕
            while ((read_data=fileInputStream.read())!=-1){
                System.out.print((char) read_data);

            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭文件流
            fileInputStream.close();
        }
    }

结果:

这里我们用字节流处理文本文件,在读英文的时候不会出现异常,但如果是中文会出现乱码,而且效率较低。 

因为我们这里是单个字节的读取我们用read(byte[] b)方法优化:

@Test
    public void readFile02() throws IOException {
        String filePath="e:\\news2.txt";
        int read_data=0;
        //定义一个字节数组
        byte[] buf=new byte[8];
        int read_length=0;
        FileInputStream fileInputStream=null;
        try {
            //创建FileInputStream对象
            fileInputStream = new FileInputStream(filePath);
            //fileInputStream.read(buf) 返回实际读取的字节数 表示读取完毕

            while ((read_length=fileInputStream.read(buf))!=-1) {
                System.out.print(new String(buf,0, read_length));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭文件流
            fileInputStream.close();
        }
    }

结果:

4.OutputStream:字节输出流

 OutputStream抽象类是所有类字节输出流的子类

常用的子类介绍:

  1. FileOutputStream:文件输入流
  2. BufferedOutputStream:缓冲字节输入流
  3. ObjectOutputStream:对象字节输入流

FIleOutputStream类

1.FileOutputStream介绍
    • Constructor and Description
      FileOutputStream(File file)

      创建文件输出流以写入由指定的 File对象表示的文件。

      FileOutputStream(File file, boolean append)

      创建文件输出流以写入由指定的 File对象表示的文件。

      FileOutputStream(FileDescriptor fdObj)

      创建文件输出流以写入指定的文件描述符,表示与文件系统中实际文件的现有连接。

      FileOutputStream(String name)

      创建文件输出流以指定的名称写入文件。

      FileOutputStream(String name, boolean append)

      创建文件输出流以指定的名称写入文件。

    • Modifier and TypeMethod and Description
      voidclose()

      关闭此文件输出流并释放与此流相关联的任何系统资源。

      protected voidfinalize()

      清理与文件的连接,并确保当没有更多的引用此流时,将调用此文件输出流的 close方法。

      FileChannelgetChannel()

      返回与此文件输出流相关联的唯一的FileChannel对象。

      FileDescriptorgetFD()

      返回与此流相关联的文件描述符。

      voidwrite(byte[] b)

      b.length个字节从指定的字节数组写入此文件输出流。

      voidwrite(byte[] b, int off, int len)

      len字节从位于偏移量 off的指定字节数组写入此文件输出流。

      voidwrite(int b)

      将指定的字节写入此文件输出流。

 2.代码:

@Test
    public void writeFile() throws IOException {
        FileOutputStream fileOutputStream=null;
        String filePath="e:\\a.txt";

        try {
            fileOutputStream=new FileOutputStream(filePath,true);
//            //写入一个字节
//            fileOutputStream.write('A');
            //写入字符串
            String str="hello,world";
            fileOutputStream.write(str.getBytes());
            //这种创建流的方式,是覆盖创建方式 当写入内容时会覆盖原先的内容



        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            fileOutputStream.close();
        }
    }
}

如果在创建文件流的时候,我们使用默认打开方式。你会发现,每次写文件,他都是从文件开头开始输入的,并且创建对象的时候如果路径文件不存在会自动创建一个。

FileOutputStream

  • public FileOutputStream(String name, boolean append) throws FileNotFoundException
  • 创建文件输出流以指定的名称写入文件。 如果第二个参数是true ,则字节将写入文件的末尾而不是开头。 创建一个新的FileDescriptor对象来表示此文件连接。
  • 首先,如果有一个安全管理员,它的checkWrite方法是以name作为参数来调用的。
  • 如果文件存在但是是一个目录而不是常规文件,不存在但不能创建,或者由于任何其他原因无法打开,那么抛出一个FileNotFoundException
  • 参数
  • name - 与系统相关的文件名
  • append - 如果是 true ,那么字节将被写入文件的末尾,而不是开头
  • 异常
  • FileNotFoundException - 如果文件存在但是是一个目录而不是常规文件,不存在但不能创建,或由于任何其他原因无法打开。
  • SecurityException - 如果安全管理器存在,并且其 checkWrite方法拒绝对该文件的写入访问。

所以如果你想在文件内末尾写入内容,而不会覆盖原先内容。在创建流对象的时侯,将append置为true

5.文件的拷贝

例子:将e盘中的image.png拷贝到d:\\

分析:

  1. 创建文件输入流,将文件读入该程序
  2. 创建文件的输出流,将读取到的文件数据写入指定的文件

代码:

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

public class FileCopy_ {
    public static void main(String[] args) throws IOException {
        //完成文件拷贝
        String filePath="e:\\image1.png";
        String destFilePath="d:\\copy.png";
        FileInputStream fileInputStream=null;
        FileOutputStream fileOutputStream=null;

        try {
            fileInputStream=new FileInputStream(filePath);
            fileOutputStream=new FileOutputStream(destFilePath);
            byte[] buff= new byte[1024];
            int readLen=0;
            while ((readLen=fileInputStream.read(buff))!=-1){
                fileOutputStream.write(buff,0,readLen);

            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(fileOutputStream!=null){
                fileOutputStream.close();
            }
            if (fileInputStream!=null){
                fileInputStream.close();
            }
        }
    }

}

 6.FileReader和FileWriter介绍

FileReader和FileWriter是字符流,即按照字符来操作io

1.FileReader类

 FileReader相关方法:

  • new FileReader(File/String)
  • read();每次读取一个字符
  • read(char[]):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1

 相关API

  • new String(char[]);将char转换成String
  • new String(char[],off,len);将char[]的指定部分转换成String
 @Test
    public void FileRead01() throws IOException {
        String filePath="e:\\a.txt";
        FileReader fileReader=null;
        int data=0;
        try {
            fileReader=new FileReader(filePath);
            //循环读取
            while ((data=fileReader.read())!=-1){
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fileReader!=null){
                fileReader.close();
            }
        }
    }

我们用字符数组来改进这个读取代码:

@Test
    //用字符数组读取
    public void FileRead02() throws IOException {
        String filePath="e:\\a.txt";
        FileReader fileReader=null;
        int data=0;
        int readLen=0;
        char[] buff=new char[8];
        try {
            fileReader=new FileReader(filePath);
            //循环读取
            while ((readLen=fileReader.read(buff))!=-1){
                System.out.print(new String(buff,0,readLen));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fileReader!=null){
                fileReader.close();
            }
        }
    }

2.FileWriter类

 

FileWriter常用方法:

  • new File(File/String):覆盖模式,相当于流的指针在首段
  • new FileWriter(File/String,true):追加模式,流的指针在末尾
  • write(int):写入单个字符
  • write(char[]):写入指定数组 
  • write(char[],off,len):写入指定数组的指定部分
  • write(String):写入整个字符串
  • write(string,off,len):写入字符串的指定部分
  • 相关API:String类:toCharArray:将String转换成char[]

注意:

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

代码:

 @Test
    public void FileWriter01() throws IOException {
        String filePath="e:\\note.txt";
        FileWriter fileWriter=null;
        char[] chars={'a','b','c'};
        try {
            fileWriter=new FileWriter(filePath);
            //写入单个字符
            fileWriter.write('H');
            //写入指定数组
            fileWriter.write(chars);
            //写入字符数组
            fileWriter.write("tttyyyzzz".toCharArray(),0,4);
            //写入整个字符串
            fileWriter.write("hello word");
            //指定字符串的部分
            fileWriter.write("shangHai",0,2);

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fileWriter!=null){
                fileWriter.close();
            }
        }
    }

7.节点流和处理流

1.基本介绍:

  1. 节点流可以从一个特定的数据源读写数据,如FIleReader,FileWriter
  2. 处理流(也叫包装流)是“连接”已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能如BufferedReader,BufferedWriter

2.区别和联系

  1. 节点流 是底层流/低级流,直接跟数据源相接。
  2. 处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。
  3. 处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连

3.功能区别:

  1. 性能的提高:主要以增加缓冲的方式来提高输入输出的效率。
  2. 操作的便捷:处理流可能提供了一系列便捷的方法来一次输出输入大批量的数据,使更加灵活方便。

 4.模拟底层代码理解:

模拟修饰器设计模式:

模拟Reader

public abstract class Reader_ {
    public void readFile(){};
    public void readString(){};
}

模拟节点流:

public class FileReader_  extends Reader_{
    public void readFile(){
        System.out.println("对文件读取");
    }
}
public class StringReader_ extends Reader_{
    public void readString(){
        System.out.println("读取字符串");
    }
}

模拟处理流:

public class BufferedReader_ extends Reader_{
    private Reader_ reader_;

    public BufferedReader_(Reader_ reader_) {
        this.reader_ = reader_;
    }
    public void readFiles(int n){
        for (int i = 0; i < n; i++) {
            reader_.readFile();
        }
    }
    public void readString(int n){
        for (int i = 0; i < n; i++) {
            reader_.readString();
        }
    }
}

案例:

public class text {
    public static void main(String[] args) {
        BufferedReader_ bufferedReader = new BufferedReader_(new FileReader_());
        bufferedReader.readFiles(10);
        BufferedReader_ bufferedReader1=new BufferedReader_(new StringReader_());
        bufferedReader1.readString(10);
    }
}

运行结果:

我们可以看到,我们用一个Buffered类去模拟处理流,用另外两个去模拟节点流。我们可以发现,我们的处理流其实就在对节点流的数据以及一些功能进行二次封装。使得更加方便 

8.BufferedReader和BuffereredWriter类

BufferedReader和BuffereredWriter类属于字符流,是按照字符来读取数据的。关闭时,处理流只需要关闭外层流即可。

1.BufferedReader类

继承图表

代码: 

@Test
    public void ReadFile01() throws IOException {
        String filePath="e:\\note.txt";
        BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
        String line;
        while ((line=bufferedReader.readLine())!=null){
            System.out.println(line);
        }
        //只需要关闭bufferedReader就可以了
        bufferedReader.close();
    
    }

2.BufferedWriter类

代码:

@Test
    public void fileRead01() throws IOException {
        //创建一个
        String filePath="e:\\Ok.txt";
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
        bufferedWriter.write("hello word ,tomorrow");
        bufferedWriter.newLine();//插入一个换行符
        bufferedWriter.write("hello2 word ,tomorrow");
        bufferedWriter.newLine();//插入一个换行符
        bufferedWriter.write("hello3 word ,tomorrow");
        bufferedWriter.newLine();//插入一个换行符
        bufferedWriter.write("hello4 word ,tomorrow");
        bufferedWriter.newLine();//插入一个换行符


        bufferedWriter.close();

    }

 9.BufferedInputStream和BufferedOutputStream类

1.BufferedInputStream类

BufferedInputStream是字节流,在创建BufferedInputStream时会创建一个内部缓冲区数组

    • 构造方法  
      Constructor and Description
      BufferedInputStream(InputStream in)

      创建一个 BufferedInputStream并保存其参数,输入流 in ,供以后使用。

      BufferedInputStream(InputStream in, int size)

      创建 BufferedInputStream具有指定缓冲区大小,并保存其参数,输入流 in ,供以后使用。

    • Modifier and TypeMethod and Description
      intavailable()

      返回从该输入流中可以读取(或跳过)的字节数的估计值,而不会被下一次调用此输入流的方法阻塞。

      voidclose()

      关闭此输入流并释放与流相关联的任何系统资源。

      voidmark(int readlimit)

      见的总承包 mark的方法 InputStream

      booleanmarkSupported()

      测试这个输入流是否支持 markreset方法。

      intread()

      readInputStream的一般合同。

      intread(byte[] b, int off, int len)

      从给定的偏移开始,将字节输入流中的字节读入指定的字节数组。

      voidreset()

      resetInputStream的一般合同。

      longskip(long n)

      skipInputStream的一般合同

2.BufferedOutputStream类

BufferedOutputStream是字节流,实现缓冲的输出流,可以将多个字节写入底层输出流中,而不必对每次字节写入调用底层系统。

    • 构造方法  
      Constructor and Description
      BufferedOutputStream(OutputStream out)

      创建一个新的缓冲输出流,以将数据写入指定的底层输出流。

      BufferedOutputStream(OutputStream out, int size)

      创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流。

    • 所有方法  接口方法  具体的方法 
      Modifier and TypeMethod and Description
      voidflush()

      刷新缓冲输出流。

      voidwrite(byte[] b, int off, int len)

      从指定的字节数组写入 len个字节,从偏移 off开始到缓冲的输出流。

      voidwrite(int b)

      将指定的字节写入缓冲的输出流。

 案例:

public class BufferedCopy_ {
    public static void main(String[] args) throws IOException {
        String filePath="e:\\image1.png";
        String filePath2="e:\\hsp.png";

        BufferedInputStream bufferedInputStream=null;
        BufferedOutputStream bufferedOutputStream=null;


        bufferedInputStream=new BufferedInputStream(new FileInputStream(filePath));
        bufferedOutputStream=new BufferedOutputStream(new FileOutputStream(filePath2));

        byte[] buff=new byte[1024];
        int readLen=0;
        while ((readLen=bufferedInputStream.read(buff))!=-1){
            bufferedOutputStream.write(buff,0,readLen);

        }
        if (bufferedInputStream!=null) {
            bufferedInputStream.close();
        }
        if (bufferedOutputStream!=null) {
            bufferedOutputStream.close();
        }

    }
}

使用处理流可以对二进制拷贝。字节流可以操作二进制文件,也可以操作文本文件。但字符型只能是文本文件。

10.对象流

ObjectInputSteam和ObjectOutputStream,我们来看一个需求来理解,

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

 1.基本介绍:

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

2.代码

1.序列化 

public class ObjectOutStream_ {
    public static void main(String[] args) throws IOException {
        String filePath="e:\\data.dat";
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(filePath));

        oos.write(100);//Integer 实现了Serializable//
        oos.writeBoolean(true);
        oos.writeChar('a');
        oos.writeDouble(3.2);
        oos.writeUTF("tzhcesw");
        oos.writeObject(new Dog("旺财",12));

    }
}
class Dog implements Serializable {
    private String name;
    private int age;

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

 2.反序列化

public class ObjectInputStream_ {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        String filePath="e:\\data.dat";
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream(filePath));
        //读取序列化的顺序和保存数据(序列化)的顺序一致
        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);
        ois.close();

    }
}
class Dog implements Serializable {
    private String name;
    private int age;

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

注意事项和细节说明:

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

11.转换流 

InputStreamReader和OutputStreamWriter

1.介绍

  • InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成Reader(字符流)
  • OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)包装成Writer(字符流)
  • 当处理纯文本数据时,如果使用字符流的效率最高,并且可以有效解决中文问题,所以将字节流转换成字符流。
  • 可以在使用的时候指定编码格式。

 1.InputStreamReade类

代码:

public class InputStreamReader_ {
    public static void main(String[] args) throws IOException {
        String filePath="e:\\a.txt";
        InputStreamReader isr=new InputStreamReader(new FileInputStream(filePath),"gbk");
        BufferedReader br=new BufferedReader(isr);
        String s=br.readLine();
        System.out.println(s);
        br.close();
    }
}

先将FileInputStream类转换成gbk编码(字符流),再用BufferedReader类包装,去读取文件。相当于包装了两次。

 2.OutputStreamWriter类

代码: 

public class OutputStreamWriter_ {
    public static void main(String[] args) throws IOException {
        String filePath="e:\\hsp.txt";
        String charSet="utf-8";
        OutputStreamWriter osk = new OutputStreamWriter(new FileOutputStream(filePath), charSet);
        osk.write("tzy 早上好");
        osk.close();
        System.out.println("按照"+charSet+"保存");

    }
}

同上,也是两次包装,可以改变编码格式。将字节流转换成字符流。

12.打印流 

PrintStream和PrintWriter类

1.PrintStream类

代码: 

public class PrintStream_ {
    public static void main(String[] args) throws IOException {
        //再默认情况下,PrintStream 输出数据的位置是 标准输出,即显示器
        PrintStream out=System.out;
        out.print("joo hello");
        //out.println();
        //print方法的底层是write
        out.write("tzy good morening".getBytes());
        out.close();

        //我们去修改打印流输出的位置
        System.setOut(new PrintStream("e:\\f1.txt"));
        System.out.println("hello word");
        
    }
}

2. PrintWriter类

代码: 

public class PrintWriter_ {
    public static void main(String[] args) throws IOException {
        PrintWriter printWriter = new PrintWriter(System.out);
        printWriter.println("hi bingk");
        printWriter.close();
        
        PrintWriter printWriter1 = new PrintWriter(new FileWriter("e:\\f2.txt"));
        printWriter1.println("hi bingk");
        printWriter1.close();
        
        
    }
}

 13.Properties类

  • 看一个问题:
  • 一个编程文件:mysql.properies
  • ip=192.168.0.12
  • user=root
  • pwd=12345
  • 需求:读取ip,user,pwd的值

传统方法:

public class Properties01 {
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new FileReader("D:\\Java_data\\tankgame\\Properties_\\mysql.properties"));
        String Line="";
        while ((Line= br.readLine())!=null){
           String[] spli= Line.split("=");
            System.out.println(spli[0]+"=="+spli[1]);
            
        }
        br.close();
    }
}

 1.基本介绍:

  1. 专门用于读取配置文件的集合类,配置文件格式:key=value
  2. 注意:键值对不需要有空格,值不需要用引号,默认类型是String
  3. Properties的常见方法:
    • Modifier and TypeMethod and Description
      StringgetProperty(String key)

      使用此属性列表中指定的键搜索属性。

      StringgetProperty(String key, String defaultValue)

      使用此属性列表中指定的键搜索属性。

      voidlist(PrintStream out)

      将此属性列表打印到指定的输出流。

      voidlist(PrintWriter out)

      将此属性列表打印到指定的输出流。

      voidload(InputStream inStream)

      从输入字节流读取属性列表(键和元素对)。

      voidload(Reader reader)

      以简单的线性格式从输入字符流读取属性列表(关键字和元素对)。

      voidloadFromXML(InputStream in)

      将指定输入流中的XML文档表示的所有属性加载到此属性表中。

      Enumeration<?>propertyNames()

      返回此属性列表中所有键的枚举,包括默认属性列表中的不同键,如果尚未从主属性列表中找到相同名称的键。

      voidsave(OutputStream out, String comments)已弃用

      如果在保存属性列表时发生I / O错误,此方法不会抛出IOException。 保存属性列表的store(OutputStream out, String comments)方法是通过store(OutputStream out, String comments)方法或storeToXML(OutputStream os, String comment)方法。

      ObjectsetProperty(String key, String value)

      致电 Hashtable方法 put

      voidstore(OutputStream out, String comments)

      将此属性列表(键和元素对)写入此 Properties表中,以适合于使用 load(InputStream)方法加载到 Properties表中的格式输出流。

      voidstore(Writer writer, String comments)

      将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式输出到输出字符流。

      voidstoreToXML(OutputStream os, String comment)

      发出表示此表中包含的所有属性的XML文档。

      voidstoreToXML(OutputStream os, String comment, String encoding)

      使用指定的编码发出表示此表中包含的所有属性的XML文档。

      Set<String>stringPropertyNames()

      返回此属性列表中的一组键,其中键及其对应的值为字符串,包括默认属性列表中的不同键,如果尚未从主属性列表中找到相同名称的键。

2.代码 

public class Properties02 {
    public static void main(String[] args) throws IOException {

        Properties properties = new Properties();
        //加载配置文件
        properties.load(new FileReader("D:\\Java_data\\tankgame\\Properties_\\mysql.properties"));
        //把K-V显示
        properties.list(System.out);

        String ip =properties.getProperty("ip");
        String user =properties.getProperty("user");
        String pwd =properties.getProperty("pwd");
        System.out.println("ip ="+ip);
        System.out.println("用户名 ="+user);
        System.out.println("密码 ="+pwd);

        //创建
        Properties properties1 = new Properties();
        properties1.setProperty("charSet","utf-8");
        properties1.setProperty("user","tom");
        properties1.setProperty("pwd","abc111");//如果该文件没有key就是创建,有就是修改

        properties1.store(new FileOutputStream("D:\\Java_data\\tankgame\\Properties_\\mysql1.properties"),"helloword");
        System.out.println("success~");


    }
}

 代码介绍了对propecties文件的读取创建以及修改。

  • 33
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值