Java IO 流

SAP S4 MM模块自动记账全流程解析:从评估范围到科目分组的实战配置 本文深入解析SAP S4 MM模块自动记账的全流程,从核心概念评估范围与评估控制入手,详细阐述了评估类、科目分组等关键配置的逻辑关系。通过实战配置步骤,指导如何建立从物料移动(如收货、发料)到自动生成准确财务凭证的完整体系,确保库存价值与总账实时同步,为企业构建可靠的财务业务一体化基石。 阅读详情

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 {
    }
}
PyTorch 面试题及参考答案(精选100道) 模块是 PyTorch 中用于自动求导的核心模块。它为张量上的所有操作提供了自动求导的功能。在深度学习中,反向传播是一种用于计算损失函数相对于模型参数的梯度的算法。通过梯度,我们可以使用优化算法(如随机梯度下降)来更新模型的参数,从而最小化损失函数。模块的主要作用就是自动计算这些梯度。当我们创建一个张量时,如果将其属性设置为True,那么 PyTorch 会跟踪该张量上的所有操作。在完成前向传播计算出损失函数后,调用方法,模块会自动根据链式法则反向传播计算出所有需要求导的张量的梯度。 阅读详情

相关推荐

Python与西门子PLC数据交互实战:基于Snap7的跨平台工业通信指南

本文详细介绍了如何使用Python和Snap7库实现与西门子PLC的数据交互。内容涵盖跨平台环境搭建、连接参数配置、数据读写实战及性能优化技巧,为工业自动化、数据采集和智能制造场景提供了一套轻量、灵活且高效的通信解决方案。

vim8coder的博客 282

Java中throws IOException什么意思?

throws IOException是Java中的throws语句。 throws是方法可能抛出异常的声明。(用在声明方法时,表示该方法可能要抛出异常) 语法:[(修饰符)](返回值类型)(方法名)([参数列表])[throws(异常类)]{......} public void doA(int a) throws  Exception1,Exception3{......} 举例: ...

qq_42058441的博客 4万+

mac(apple silicon)arm64安装spm12详细教程

3.下载matlab runtime R2023b for macOS (macA64),注意必须下载这个,只下载matlab是不可以的。默认安装目录是/Applications/MATLAB/MATLAB_Runtime/R2023b。注意最后的命令,路径根据自己的matlab_runtime安装位置进行调整,然后就可以安装成功了。5. 解压spm12.zip,解压后将文件夹拖到应用程序下(Applications)2.下载spm12,这个版本可兼容mac芯片!6.打开mac终端,输入。

weixin_62332001的博客 2020

Java基础——方法的异常说明throws关键字在类的继承中的限制规则

定义 引用《Java 编程思想》中文版第四版对throws的说明: “异常说明属于方法声明的一部分,紧跟在形式参数列表之后,使用了附加的关键字throws,后面接一个所有潜在异常类型的列表。” 问题一 那么既然对“方法潜在异常类型”声明在了方法形式参数后,那么是否在继承中子类重写父类方法时,子类的方法声明后面也要受父类方法的约束抛出父类指定的异常? 测试 public class...

qq_27752085的博客 2126

Maxwell个人初学经验及资料分享

前段时间学习了课题组基于Maxwell所建立的模型,因为以前从来没有使用过,只是按照一步一步记忆了操作,但总觉得不熟悉,我想是缺乏对这个软件整体的了解,真正想上手只会这一个模型也没有办法扩展。但是我感觉这些有限元分析软件学习起来应该有一些共性,基于以前对COMSOL学习的一点经验,我就在官网和其他网站找了一些学习资源构成一条基础入门之路,也可能有更好的资源,仅代表个人观点做一下分享。以上就是本人对该软件初步学习的一点理解,跟着这样的操作不到一个星期就能初步的掌握。...

怎么又是萝卜的博客 5631

【FF-A】第二章 Introduction

Armv8.4 架构引入了在安全状态下的虚拟化扩展。Arm® SMMU v3.2 架构[1]为安全流添加了对第2阶段翻译的支持,以补充在 Armv8.4 处理器状态下的安全 EL2 翻译制度。这些架构特性使得在安全状态下,彼此不信任的软件组件能够相互隔离。关于在安全状态下引入虚拟化扩展以及固件框架目标的更多理念可在名为《在安全世界使用虚拟化进行隔离》的白皮书[3]中找到。软件组件只能访问物理地址空间和系统资源的区域,例如 GIC 中对其正确运行必要的中断。

baron-周贺贺-代码改变世界ctw 528

错误:未报告的异常 java.io.IOException;必须对其进行捕捉或声明以便抛出

原因:1某些方法有IO操作,但此方法后没有添加throws   IOException ,只需在此方法声明后加上即可。         2在可能出错的地方加一段try{}catch{}就好了,因为JAVA程序必须对可能发生的异常进行处理

X站 1万+

GEE聚类分析:基于sentinel-2 影像进行 K-Means 聚类分析

这篇博客介绍了如何使用 Google Earth Engine (GEE) 进行 K-Means 聚类分析,以识别感兴趣区域(ROI)内的不同地表覆盖类型。文章详细说明了从定义用户参数、准备参考区域、加载和预处理 Sentinel-2 图像,到训练 K-Means 聚类器并对图像进行聚类的完整流程。代码示例展示了如何设置参数、采样像素数据、训练聚类器,并将结果可视化。最后,还提供了将聚类结果导出到 Google Drive 的选项。通过该教程,用户可以掌握在 GEE 平台上进行地理数据聚类分析的基本方法。

此星光明博客 263

java基础语法10--异常

异常处理概述 异常(Exception)是程序在执行过程中所产生的问题。导致异常的产生的原因有很多种,包括:用户输入了无效的数据、找不到一个需要打开的文件、在通讯过程中网络连接断开或者JVM发生了内存溢出等等。 有些异常是由于用户的错误所导致的,有些是由程序员的错误导致的,有些则是由硬件设备的故障导致的。在本章中,我们将详细介绍不同类型的异常,以及在什么时候应该抛出一个异常,在什么时候应该捕获...

IT_CREATE的博客 581

【Simulink教程案例9】基于simulink的BPSK,QPSK调制解调通信系统建模与仿真——使用simulink自带模块设计

BPSK (Binary Phase Shift Keying)-------二进制相移键控。是把模拟信号转换成数据值的转换方式之一,利用偏离相位的复数波浪组合来表现信息键控移相方式。BPSK使用了基准的正弦波和相位反转的波浪,使一方为0,另一方为1,从而可以同时传送接受2值(1比特)的信息。BPSK的映射关系如下所示:BPSK调制过程将输入的1010二进制数据中的0都转化为-1,使得非极性码变为极性码。

FPGA/MATLAB学习教程/源码/项目合作开发 3484

matlab 一维相位解缠

一维相位解缠算法的matlab代码实现。

点云侠的博客 372

JAVA高级-IO流

IO流 File类 说明 java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关 File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。 如果需要访问文件内容本身,则需要使用输入/输出流。 想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对 象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录。 File对象可以作为参数传递给流的构造器 相对路径:IDEA在单元测试中,本module中下的路径,在

weixin_47303191的博客 509

最详细的 SAP ABAP Web Service 创建和消费步骤讲解

本文原版发表于 SAP 官方社区,当时用的英文版写作,标题为:Step by step to create, consume and trace web service in ABAP system https://blogs.sap.com/2014/05/20/step-by-step-to-create-consume-and-trace-web-service-in-abap-system/ 总共阅读量超过 18 万。 How to create web service provider in A

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 3150

Java IO流详解

原文 Java IO流详解 1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。Java的I/O流提供了读写数据的标准方法。任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法。 IO又分为流IO(java.io)和块IO(java.nio) Java.io是大多数面向数据流的输入/输出类的主要软件包。此外,Java也对块传输提供支持,在核心库 java.nio中采用的

ss810540895的博客 1万+

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

【Java IO流】IO流详解

IO,即InputOutput,也就是输入和输出,指应用程序和外部设备之间的数据传递,常见的外部设备包括磁盘文件、管道、网络连接Java中是通过流处理IO的,那么什么是流?流(Stream),是一个抽象的概念,是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通道当Java程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是磁盘文件、内存、网络连接等等。类似地,当Java程序需要写入数据的时候,就会开启一个通向目的地的流。

m0_55908255的博客 1695

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Java IO流知识点总结

I(Input)O(Output) 通过IO可以处理程序与外部环境之间的数据传输。

weixin_43836337的博客 1868

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Java IO流之IO流基础

IO流介绍 IO基础之File类 IO流之字符流 IO流之字节流 IO流之Scanner类

Mr.mooye 2848

Java——IO流

存储和读取数据的解决方案IO流和File是息息相关的。

pangyaqi的博客 1707

java IO流学习总结

学习了几天的java IO流,下面我来谈谈对java 输入输出流IO的个人见解吧! 转载自:https://blog.csdn.net/zhaoyanjun6/article/details/54292148/ java流类结构图 一.流的概念: 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。它的特性是进行数据传输; 例如从水源地长江把水导入自来水厂,然后又从自...

coder150806的博客 5万+

Java的File与IO流

File类位于java.io包下,是文件和目录路径名的抽象表示,提供了一系列对文件和文件夹本身操作的方法,它不能读写数据。read(字节数组)一次性读取多个字节,注意要判断实际读取的字节到底有多少,以免错误地读取字节数组之前遗留的数据。默认缓冲池大小为8KB。注意:File类是路径名的抽象表示,构建一个File实例并不会创建一个文件,不管文件是否存在,都可以创建任意文件名的File实例。[] listFiles() 一级文件对象数组,包含隐藏文件,无权限访问则为null,主调为文件也为null。

m0_73077892的博客 1829

java中的IO流

如果new的File对象所表示的文件或目录并不存在,那么并不会应位new了一个File对象,操作系统就在对应的路径下创建所对应的文件和目录,它仅仅是在JVM的堆中new了一个File对象而已。java为了避免这种类型安全性问题的发生,使序列化接口类在每次编译时,自动生成一个序列化版本ID,用以区别不同的版本,当序列化和反序列化的版本不一致时,就会失败,抛出异常。然而,有些修改并不影响对象的反序列化,如类中加入了新的实例变量,而序列化的数据中并没有新实例变量的值,那么它在反序列化的过程中可以使默认值。

冲出仁川,走出马德里,故事还会再继续 2526

java基础——IO流

是字节输入流,用于从文件中读取字节数据。int data;= -1) {

2403_87486006的博客 795

java io流不关闭有什么后果_Java IO流

一、基本概念 IO是Java对数据的操作是通过流的方式,数据传输是需要通道的,而IO流就是数据传输的通道。IO流可以形象的比喻为运送货物的传输带。IO流用来处理设备之间的数据传输,上传文件和下载文件,Java用于操作流的对象都在IO包中。总结一下,Java IO输入机制就是为了允许程序读取外部数据(包括来自于磁盘、光盘等存储设备的数据)和用户输入的数据。 Java的IO流通过java...

weixin_39563827的博客 2325

IO流【Java】

IO流的系统学习笔记

amazing2024的博客 1162

Java IO流

Java IO 也称为IO流,IO = 流,它的核心就是对文件的操作,对于 字节 、字符类型的输入和输出流。 IO是指对数据流的输入和输出,也称为IO流,IO流主要分为两大类,字节流和字符流。字节流可以处理任何类型的数据,如图片,视频等,字符流只能处理字符类型的数据。 IO流的本质是数据传输,并且流是单向的。 常用的字节流FileInputStream、FileOutputStream、ObjectInputStream、ObjectOutputStream。 IO分阻塞型IO和非阻塞型IO(.

rmkloveme 1352

java io流_Java——IO流超详细总结

该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架。在初学Java时,IO流是我遇到的一个很头疼的东西,Java IO 体系看起来类很多,感觉很复杂,但其实是 IO 涉及的因素太多了。在设计 IO 相关的类时,编写者也不是从同一个方面考虑的,所以会给人一种很乱的感觉,并且还...

weixin_39838362的博客 2162
上一篇: Java8 新特性之 新时间日期 API
下一篇: 线程池学习笔记
凌逸轩
博客等级 码龄10年 16粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值