Java IO 流

Java IO 流

文件

概念

  • 文件:保存数据的地方

在这里插入图片描述

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

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

  • 输出流:数据从程序(内存)到数据源的路径

常用的文件操作

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

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

代码实例

package javaio;

import org.junit.jupiter.api.Test;

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


public class CreateFile {
    // 方式一:new File(String pathname)
    @Test
    public void createFile01() throws IOException {
        String filePath = ".\\file1.txt";
        File file = new File(filePath);
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("file1, 文件创建成功");
    }

    // 方式二:new File(File parent,String child)   //根据父目录文件 + 子路径构建
    @Test
    public void createFile02() throws IOException {
        File parentFile = new File(".\\");
        String fileName = "file2.txt";
		
        // 此时还在内容中
        File file = new File(parentFile, fileName);
        try {
            // 实际创建完成在此处
            file.createNewFile();
            System.out.println("file2, 文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 方式三:new File(String parent,String child) //根据父目录 + 子路径构建
    @Test
    public void createFile03() throws IOException {
        String fileName = "file3.txt";
        String path = ".\\";

        // 此时还在内容中
        File file = new File(path, fileName);
        try {

            // 实际创建完成在此处
            file.createNewFile();
            System.out.println("file3, 文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {

    }
}

获取文件的相关信息

getName、getAbsolutePath、getParent、length、exitsts、isFile、isDirectory

package javaio;

import org.junit.jupiter.api.Test;

import java.io.File;

public class GetFileInfo {
    @Test
    public void getFileInfo() {
        // 先创建文件对象
        File file = new File(".\\file3.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.isDirectory());
    }

    public static void main(String[] args) {

    }
}

目录的操作和文件删除

mkdir 创建一级目录,mkdirs 创建多级目录,delete 删除空目录或文件,在 Java中目录也被当成文件

package javaio;

import org.junit.jupiter.api.Test;

import java.io.File;

public class Directory {

    @Test
    public void deleteFile() {
        String filePath = ".\\file4.txt";

        File file = new File(filePath);
        if (file.exists()) {
            if (file.delete()) {
                System.out.println("文件删除成功");
            } else {
                System.out.println("文件没有删除成功");
            }
        } else {
            System.out.println("文件不存在");
        }
    }


    // 删除当前路径下的 abc 目录
    @Test
    public void deleteDirec() {
        String filePath = ".\\abc";

        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 operateDirec() {
        String filePath = ".\\a\\b\\c";

        File file = new File(filePath);
        if (file.exists()) {
            System.out.println("目录存在");
        } else {

            //if(file.mkdir())  创建一级目录
            if(file.mkdirs()){  // 创建多级目录
                System.out.println("目录创建成功");
            }else{
                System.out.println("目录创建失败");
            }
        }
    }

    public static void main(String[] args) {

    }
}

IO流原理及流的分类

Java IO流原理

  • I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理数据传输。如读/写文件,网络通讯等。
  • Java程序中,对于数据的输入/输出操作以”流(stream)”的方式进行。
  • java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据

在这里插入图片描述

  • 输入 input: 读取外部数据 (磁盘、光盘等存储设备的数据)到程序(内存)中。
  • 输出output: 将程序(内存) 数据输出到磁盘、光盘等存储设备中

流的分类

按操作数据单位不同分为: 字节流(8 bit)二进制文件【声音,视频,word 文件】,字符流(按字符)【文本文件】

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

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

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

在这里插入图片描述
数据就相当于这里的物品,外卖小哥充当输入和输出流的作用,从用户那里派送物品到物流中心,也将物流中心的物品派送给用户

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

IO 流体系—常用的类

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

InputStream 常用子类:

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

输入流

InputStream 字节输入流: 是所有类字节输入流的超类

1、FileInputStream 文件输入流[字节流]

构造方法摘要

方法方法描述
FileInputStream(File file)通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File对象file指定。
FileInput Stream(FileDescriptor fdObj)通过使用文件描述符fdObj创建一个 FileInputStrean,该文件描述符表示到文件系统中某个实际文件的现有连接。
FileInput Stream(String name)通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名name指定。

方法摘要

方法方法描述
int available()返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。
void close()关闭此文件输入流并释放与此流有关的所有系统资源。
protect void finalize()确保在不再引用文件输入流时调用其close方法。
FileChannel getChannel()返回与此文件输入流有关的唯一FileChannel对象。
FileDescriptor getFD()返回表示到文件系统中实际文件的连接的FileDescriptor 对象,该文件系统正被此FileIngutStream使用。
int read()从此输入流中读取一个数据字节。
int read (byte[] b)从此输入流中将最多 b.length个字节的数据读入一个 byte 数组中。
int read (byte[] b, int off,int len)从此输入流中将最多len个字节的数据读入一个 byte 数组中。
long skip (long n)从输入流中跳过并丢弃n个字节的数据。

FileInputStream

package javaio.inputstream;


import org.junit.jupiter.api.Test;

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

/**
 * 字节输入流 FileInputStream 每次读取单个字节,效率较低
 * 注意读取的时候使用 readByte(byte[] b)
 */
public class FileInputStream_ {
    @Test
    public void readFile01() {
        String filePath = ".//file3.txt";
        //String filePath = "E:\\QQ file receive\\2084289117\\FileRecv\\myi.txt";
        FileInputStream fileInputStream = null;
        int readData = 0;
        try {
            // 创建 fileInputStream 流对象,用于读取文件内容
            fileInputStream = new FileInputStream(filePath);


            // 从该输入流读取一个字节的数据,如果没有输入可以用,此方法将阻止
            // 如果返回 -1, 表示读取完毕
            while ((readData = fileInputStream.read()) != -1) {
                System.out.print((char) readData);  // 转换成 char 显示
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭文件流释放资源, 注意捕获异常
            try {
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public void readFile02() {
        String filePath = ".//file3.txt";
        //String filePath = "E:\\QQ file receive\\2084289117\\FileRecv\\myi.txt";
        FileInputStream fileInputStream = null;
        int readLen = 0;

        // 一次读取8个字节
        byte[] buffer = new byte[8];

        try {
            //创建FileInputStream对象,用于读取文件
            fileInputStream = new FileInputStream(filePath);

            // 从该输入流读取最多b.length字节的数据到字节数组。此方法将阻塞,直到某些输入、
            // 如果返同-1,表示读取完毕
            // 如果读取正常,返回实际读取的字节数
            while ((readLen = fileInputStream.read(buffer)) != -1) {
                System.out.println(new String(buffer, 0, readLen));  // 转换成 string 显示
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭文件流释放资源, 注意捕获异常
            try {
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {

    }
}
2、FileOutputStream 文件输出流

FileOutputStream 代码示例

@Test
public void getProperties01() throws IOException{
    String filePath = ".\\mysql.properties";
    BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));

    String line = "";
    while ((line = bufferedReader.readLine()) != null) {
        String[] split = line.split("=");
        System.out.println(split[0] + " : " + split[1]);
    }
}
package javaio.outputstream;

import org.junit.jupiter.api.Test;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;


public class FileOutStream01 {

    /**
     * 将数据写到文件中,如果文件不存在,则创建文件
     */
    @Test
    public void writeFile() {
        String filePath = ".\\file5.txt";
        FileOutputStream fileOutputStream = null;

        try {

            // 这种创建方式,当写入内容时,会覆盖原来的内容
            //fileOutputStream = new FileOutputStream(filePath);

            // 这种创建方式,当写入内容时,会追加到文件的结尾
            fileOutputStream = new FileOutputStream(filePath, true);



            // 方式一,写单个字符
            fileOutputStream.write('a');

            // 方式二: 写入一个字符串,转为 Bytes 数组
            // String.getBytes()  ==> 可以将一个字符串转为字节数组
            fileOutputStream.write("多个字节".getBytes(StandardCharsets.UTF_8));


            // 方式三:
            String str = "Java fileOutputStream";
            fileOutputStream.write(str.getBytes(), 0, str.length());

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

    public static void main(String[] args) {

    }
}
  • 将一个文件拷贝到另外一个目录,并在新的文件中添加内容

    package javaio.outputstream;
    
    import java.io.*;
    import java.nio.charset.StandardCharsets;
    
    public class FileCopy {
        public static void main(String[] args) {
            // 完成文件拷贝,将路径 D:\Desktop\微信图片_20220311171525.jpg
            // 图片拷贝到当前目录下
    
            // 思路分析
            // 1、 创建文件输入流, 将文件读入到程序
            /// 在完成程序时,应该是读取部分数据,就写入到指定的文件,这里使用循环
            // 2、 创建文件的输出流,将读取到的文件数据写入到指定的位置
            String srcFilePath = "E:\\myi.txt";
            String destFilePath = "E:\\jedis\\myi.txt";   // 当前目录下
    
            FileInputStream fileInputStream = null;
            FileOutputStream fileOutputStream = null;
    
            try {
                fileInputStream = new FileInputStream(srcFilePath);
                fileOutputStream = new FileOutputStream(destFilePath);
    
                byte[] buffer = new byte[1024];
                int readLine = 0;
    
    
                String str = "   NCOLS 1050" + "\n" +
                        "   NROWS 1050" + "\n" +
                        "   XLLCORNER -5245000" + "\n" +
                        "   YLLCORNER -5245000" + "\n" +
                        "   CELLSIZE 10000" + "\n" +
                        "   NODATA_VALUE 0" + "\n";
                fileOutputStream.write(str.getBytes(StandardCharsets.UTF_8));
    
    
                while ((readLine = fileInputStream.read(buffer)) != -1) {
                    // 读取到数据之后,就写入到文件中,一边读一边写
    
                    // 一定要使用此方法
                    fileOutputStream.write(buffer, 0, readLine);
                }
                System.out.println("文件拷贝成功");
    
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                // 关闭输入和输出流释放资源
                try {
                    if (fileInputStream != null) {
                        fileInputStream.close();
                    }
                    if (fileOutputStream != null) {
                        fileOutputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
3、FileReader 字符输入流

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

java.lang.Object
	java.io.Reader
		java.io.InputStreamReader
			java.io.FileReader

FileReader相关方法:

  1. new FileReader(File/String)

  2. read: 每次读取单个字符,返回该字符,如果到文件未尾返回 -1

  3. read(char[]): 批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1

    • 相关APl:

      new String(char[] ); 将char[]转换成String

      new String(char[] , off, len);将char[] 的指定部分转换成String

package javaio.reader_;


import org.junit.jupiter.api.Test;

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

public class FileReader_ {

    // 单个字符读取文件
    @Test
    public void readFile01() {
        String filePath = "E:\\jedis\\file2___.txt";
        FileReader fileReader = null;
        int data = 0;

        try {
            // 循环读取,使用 read 方法
            fileReader = new FileReader(filePath);
            // 单个字符的读取
            while ((data = fileReader.read()) != -1) {
                System.out.println((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileReader != null) {
                    fileReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    // 使用字符数组读取
    @Test
    public void readFile02() {
        String filePath = "E:\\jedis\\file2___.txt";
        FileReader fileReader = null;

        int readLine = 0;
        char[] buffer = new char[8];

        try {
            // 循环读取,使用 read 方法
            fileReader = new FileReader(filePath);
            // 使用read(buffer), 返回的是实际读取到的字符数
            while ((readLine = fileReader.read(buffer)) != -1) {
                System.out.println(new String(buffer, 0, readLine));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileReader != null) {
                    fileReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {

    }
}
4、FileWriter 字符输出流
java.lang.Object
    java.io.Writer
    	java.io.OutputStreamWriter
    		java.io.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):写入字符串的指定部分
    相关APl: String类: toCharArray:将String转换成char[]

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

package javaio.writer;

import org.junit.jupiter.api.Test;

import java.io.FileWriter;
import java.io.IOException;

public class FileWriter_ {

    @Test
    public void fileWrite01() {
        String filePath = ".\\note.txt";
        FileWriter fileWriter = null;

        try {
            // 采用的是覆盖写入
            //3) write(int):  写入单个字符
            fileWriter = new FileWriter(filePath);
            fileWriter.write("J");


            char[] chars = {'J', 'a', 'v', 'a'};
            //4) write(char[] ):  写入指定数组
            fileWriter.write(chars);


            //5) write(char[], off, len):  写入指定数组的指定部分
            fileWriter.write("AAAAAAAA".toCharArray(), 0, 4);


            //6) write(string): 写入整个字符串
            fileWriter.write("Java IO流文件写入");


            //7) write(string, off, len): 写入字符串的指定部分
            fileWriter.write("北京上海广州深圳", 0, 4);

            // 在数据量大的情况下,可以循环写入

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 对应 FileWriter 一定要关闭流,或者 flush 才能真正的把数据写入到文件中
                fileWriter.flush();

                // close()  相当于 flush() + 关闭
                fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("文件写入完成");
    }

    public static void main(String[] args) {

    }
}

节点流和处理流

基本介绍

  • 结点流可以从一个特定的数据源读写数据,如 FileReader、FileWriter
    在这里插入图片描述
    其他的节点流

  • 处理流(包装流)是“连接”在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,如 BufferedReader、BufferedWriter,它们采用了装饰器模式
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 节点流和处理流的区别和联系

    1. 节点流是底层流/低级流,直接跟数据源相接。

    2. 处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便方法来完成输入输出。

    3. 处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,

  • 处理流的功能主要体现在以下两个方面:

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

处理流 BufferedReader 和 BufferWriter

BufferedReader 和 BufferWriter 属于字符流,是按照字符来读取数据的,关闭时,只需要关闭外层流即可,最好处理的是文本文件。

BufferedReader 代码示例

package javaio.reader_;

import org.junit.jupiter.api.Test;

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

public class BufferedReader_ {

    @Test
    public void bufferRead() throws IOException {
        String filePath = ".\\myi.txt";

        // 创建 Bufer
        BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));

        // 存放每一行的读取结果
        String line;

        // bufferedReader.readLine() 按行读取, 如果读取到文件结尾则返回 null
        while ((line = bufferedReader.readLine()) != null) {
            System.out.println(line);
        }

        // 关闭流  调用的是 new FileReader(filePath) 这个实例
        //public void close() throws IOException {
        //    synchronized (lock) {
        //        if (in == null)
        //            return;
        //        try {
        //            in.close();
        //        } finally {
        //            in = null;
        //            cb = null;
        //        }
        //    }
        //}
        bufferedReader.close();
    }

    public static void main(String[] args) {

    }
}

BufferedWriter 代码示例

package javaio.writer;


import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriter_ {
    public static void main(String[] args) throws IOException {
        String filePath = ".\\myi__.txt";

        // 创建 Bufer
        // 如果是 new FileWriter(filePath, true) 表示以追加的方式写入
        // 如果是 new FileWriter(filePath) 表示以覆盖的方式写入
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath, true));

        bufferedWriter.write("Hello, Java");

        // 插入和系统相关的一个换行符
        bufferedWriter.newLine();
        bufferedWriter.write("Hello, Java");
        // 插入换行符
        bufferedWriter.newLine();
        bufferedWriter.write("Hello, Java");
        bufferedWriter.newLine();
        bufferedWriter.write("Hello, Java");

        bufferedWriter.close();
    }
}

BufferedReader 和 BufferWriter 相结合的文件复制示例

package javaio.reader_;

import java.io.*;

public class BufferedCopy_ {
    public static void main(String[] args) {
        //String srcFilePath = "E:\\jedis\\myi.txt";
        //String destFilePath = "E:\\jedis\\myi_modified.txt";

        String srcFilePath = "E:\\jedis\\copyImage.jpg";
        String destFilePath = "E:\\jedis\\copyImage——————.jpg";


        BufferedReader bufferedReader = null;
        BufferedWriter bufferedWriter = null;


        //1. BufferedReader 和 BufferedWriter 是按照字符操作的
        //2. 不要去操作二进制文件[声音,视频,图片,word 文档],可能造成文件损坏
        
        String line = "";
        try {
            bufferedReader = new BufferedReader(new FileReader(srcFilePath));
            bufferedWriter = new BufferedWriter(new FileWriter(destFilePath));

            // readLine() 读取一行内容,但是没有换行符
            while ((line = bufferedReader.readLine()) != null){
                // 每读取一行就写入

                // 每读取一行,就写入
                line = line.trim();
                bufferedWriter.write(line);

                // 插入换行符
                bufferedWriter.newLine();
            }

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

处理流 BufferedInputStream 和 BufferedOutputStream

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

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

图片文件拷贝示例

package javaio.reader_;


import java.io.*;

/**
 * BufferedInputStream 和 BufferedOutputStream的使用
 *
 * 字节流既可以操作二进制文件也可以操作文本文件
 */
public class BufferedCopy02_ {
    public static void main(String[] args) {
        //String srcFilePath = ".\\copyImage.jpg";
        //String destFilePath = ".\\kaolaxiong.jpg";

        String srcFilePath = "D:\\Desktop\\对比3.psd";
        String destFilePath = ".\\对比3.psd";


        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        byte[] buffer = new byte[1024];
        int readLen = 0;

        try {
            bis = new BufferedInputStream(new FileInputStream(srcFilePath));
            bos = new BufferedOutputStream(new FileOutputStream(destFilePath));

            // 当返回 -1 表示文件读取完毕
            while ((readLen = bis.read(buffer)) != -1){
                bos.write(buffer, 0 ,readLen);
            }

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

            // 关闭外层的处理流即可,底层会关闭节点流
            try {
                if(bis != null){
                    bis.close();
                }
                if(bos != null){
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

处理流 ObjectlnputStream 和 ObjectOutputStream

有一个需求
1.将int num = 100这个int数据保存到文件中,注意不是100 数字,而是int 100,并且,能够从文件中直接恢复int 100

2.将Dog dog = new Dog(“小黄”,3)这个 dog对象保存到文件中,并且能够从文件恢复.3.上面的要求,就是能够将基本数据类型或者对象进行序列化和反序列化操作

序列化和反序列化
  • 序列化就是在保存数据时,保存数据的值数据类型

  • 反序列化就是在恢复数据时,恢复数据的值数据类型

  • 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该
    类必须实现如下两个接口之一:

    Serializable // 这是一个标记接口,没有方法

    Externalizable // 该接口有两个方法需要实现

基本介绍

ObjectInputStream 类的继承结构

java.lang.Object
    java.io.InputStream
		java.io.ObjectInputStream

ObjectOutputStream 类的继承结构

java.lang.Object
    java.io.OutputStream
		java.io.ObjectOutputStream

在这里插入图片描述

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

Master 类的定义

package javaio.inputstream;
import java.io.Serializable;
public class Master implements Serializable {
}

Dog 类的序列化

package javaio.inputstream;
import java.io.Serializable;

public class Dog implements Serializable {

    // serialVersionUID 序列化的版本号,可以提高序列化的兼容性
    public static final long serialVersionUID = 1L;
    private String name;
    private int age;
    private Master master = new Master();

    // 无法序列化 static 和 transient
    private static String nation;
    private transient String color;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", color='" + color + '\'' +
                ", nation='" + nation + " " + master +
                '}';
    }
}

ObjectOutputStream 类的代码示例

package javaio.outputstream;

import javaio.inputstream.Dog;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;


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

        // 序列化之后,保存的文本格式为二进制格式,这里的 .dat 是自己指定的
        String filePath = ".\\my.dat";
        ObjectOutputStream objectOutputStream = null;

        try {
            objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePath));
            objectOutputStream.writeInt(100);
            objectOutputStream.writeBoolean(true);
            objectOutputStream.writeChar('a');
            objectOutputStream.writeDouble(9.2d);
            objectOutputStream.writeUTF("Java IO 流");

            Dog dog = new Dog("哈士奇", 3, "白色", "日本");
            objectOutputStream.writeObject(dog);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                objectOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

ObjectInputStream 的代码举例

package javaio.inputstream;


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 = ".\\my.dat";

        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filePath));

        System.out.println(objectInputStream.readInt());
        System.out.println(objectInputStream.readBoolean());
        System.out.println(objectInputStream.readChar());
        System.out.println(objectInputStream.readDouble());
        System.out.println(objectInputStream.readUTF());

        Object object = objectInputStream.readObject();
        System.out.println("运行类型 : " + object.getClass());
        System.out.println("真实的数据内容 : " + object);

        // 1. 我们希望调用 Dog 的方法,需要向下转型
        // 2. 需要我们将 Dog 类的定义,拷贝到可以引用的位置
        System.out.println(((Dog) object).getName());
        
        objectInputStream.close();
    }
}
注意事项和细节说明
  1. 读写顺序要一致

  2. 要求实现序列化或反序列化对象,需要实现Serializable

  3. 序列化的类中建议添加 SerialVersionUID, 为了提高版本的兼容性一

    public static final long serialVersionUID = 1L;
    
  4. 序列化对象时,默认将里面所有属性都进行序列化,但除了static 或 transient 修饰的成员

  5. 序列化对象时,要求里面属性的类型也需要实现序列化接口

  6. 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化

标准输入输出流 System.in 和 System.out

类型默认设备
System.in 标准输入InputStream键盘
System.out 标准输出PrintStream显示器

代码举例

package javaio.standard;

import java.util.Scanner;

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


        // System.out 编译类型 PrintStream
        // System.out 运行类型 PrintStream
        // class java.io.PrintStream
        // System.out 表示标准输出 显示器
        System.out.println(System.out.getClass());


        Scanner scanner = new Scanner(System.in);
        String next = scanner.next();

    }
}

转换流 InputStreamReader 和 OutputStreamWriter

在这里插入图片描述
介绍

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


在这里插入图片描述
代码举例

InputStreamReader 的代码示例

package javaio.transformation;


import java.io.*;

public class InputStreamReader_ {
    public static void main(String[] args) throws IOException {
        // 将字节流转换为 字符流, 注意 file3.txt 中的文件编码格式为 GBK编码
        String filePath = ".\\file3.txt";

        // 1. 把 FileInputStream 转成 InputStreamReader, 并指定 gbk 编码
        //InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk");


        // 2. 把 InputStreamReader 传入 BufferedReader
        //BufferedReader bufferedReader = new BufferedReader(isr);

        /**
         * 将 1 和 2 写到一起
         */
        BufferedReader bufferedReader = new BufferedReader(
                new InputStreamReader(
                        new FileInputStream(filePath), "gbk")
        );


        // 3. 读取
        String line = bufferedReader.readLine();
        System.out.println("读取到的内容 : " + line);


        // 4. 资源释放
        bufferedReader.close();
    }
}

OutputStreamWriter 代码示例

package javaio.transformation;


import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

/**
 * OutputStreamWriter 的使用
 */
public class OutputStreamWriter_ {
    public static void main(String[] args) throws IOException {
        // 把 FileOutputStream 字节流,转成字符流,OutputStreamWriter
        // 指定处理的编码 gbk/utf-8/utf8
        String filePath = ".\\gbk编码文件.txt";

        //String charSet = "gbk";
        String charSet = "utf-8";

        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), charSet);

        osw.write("Hi, Java 编程");

        osw.close();
        System.out.println("按照编码方式保存文件");
    }
}

打印流 PrintStream 和 PrintWriter

打印流只有输出流,没有输入流
在这里插入图片描述
示例代码

package javaio.printstream;

import java.io.IOException;
import java.io.PrintStream;

public class PrintStream_ {
    public static void main(String[] args) throws IOException {
        PrintStream out = System.out;

        // 在默认情况下, PrintStream 输出数据的位置是,标准数据,即显示器
        //public void print(String s) {
        //    if (s == null) {
        //        s = "null";
        //    }
        //    write(s);
        //}
        out.print("Java EE");

        // 以为 print的底层调用的是 write
        out.write("Java 后端开发".getBytes());
        out.close();

        // 我们可以修改打印流输出的设备
        // 修改到文件中
        System.setOut(new PrintStream(".\\修改打印位置.txt"));
        System.out.println("打印到哪里了呢?");
    }
}

在这里插入图片描述

package javaio.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(System.out);
        PrintWriter printWriter = new PrintWriter(new FileWriter(".\\printWriter.txt"));
        printWriter.print("北京你好");


        // 此时才会将数据写入文件中
        printWriter.close();
    }
}

Properties 类

在这里插入图片描述
有一个需求,如下一个配置文件 mysqI.properties

ip=192.168.0.13
user=root
pwd=12345

请问编程读取ip.user 和 pwd的值是多少 [实现代码见下文]

Properties 类对文件的要求

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

    配置文件的格式:
    键 = 值
    键 = 值

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

  3. Properties的常见方法

    • load:加载配置文件的键值对到Properties对象

    • list:将数据显示到指定设备

    • getProperty(key):根据键获取值

    • setProperty(key, value):设置键值对到Properties对象

    • store:将Properties中的键值对存储到配置文件, 在idea中,保存信息到配置文件,如果含有中文,会存储为unicode码

      http://tool.chinaz.com/tools/unicode.aspx unicode码查询工具

package javaio.properties;

import org.junit.jupiter.api.Test;

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

public class Properties_ {

    @Test
    public void getProperties01() throws IOException{
        String filePath = ".\\mysql.properties";
        BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));

        String line = "";
        while ((line = bufferedReader.readLine()) != null) {
            String[] split = line.split("=");
            System.out.println(split[0] + " : " + split[1]);
        }
    }

    /**
     * 使用 Properties 读取 properties 文件
     */
    @Test
    public void getProperties02() throws IOException{

        // 1. 创建 Properties 实例对象
        Properties properties = new Properties();

        // 2. 加载指定配置文件
        properties.load(new FileReader(".\\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 = " + user);
        System.out.println("pwd = " + pwd);
    }

    /**
     * 使用 Properties 修改 properties 文件内容
     *
     * public
     * class Properties extends Hashtable<Object,Object> {
     *
     * Properties 继承了 Hashtable
     *
     *
     */
    @Test
    public void getProperties03() throws IOException{
        // 1. 创建 Properties 实例对象
        Properties properties = new Properties();


        // 2.如果 key 存在则是修改,没有就是添加
        properties.setProperty("charset", "utf8");
        properties.setProperty("user", "隔壁老王");
        properties.setProperty("pwd", "fadsfdsafhdafadsj");
        /**
         *  public synchronized V put(K key, V value) {
         *         // Make sure the value is not null
         *         if (value == null) {
         *             throw new NullPointerException();
         *         }
         *
         *         // Makes sure the key is not already in the hashtable.
         *         Entry<?,?> tab[] = table;
         *         int hash = key.hashCode();
         *         int index = (hash & 0x7FFFFFFF) % tab.length;
         *         @SuppressWarnings("unchecked")
         *         Entry<K, V> entry = (Entry<K,V>)tab[index];
         *         for(; entry != null ; entry = entry.next) {
         *             if ((entry.hash == hash) && entry.key.equals(key)) {
         *                 V old = entry.value;
         *                 entry.value = value;
         *                 return old;
         *             }
         *         }
         *
         *         addEntry(hash, key, value, index);
         *         return null;
         *     }
         */

        properties.store(new FileOutputStream(".\\mysql___.properties"), "首行的注释信息");
        System.out.println("保存配置文件成功");
    }

    public static void main(String[] args) throws IOException {
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值