【IO】JavaIO流:字节流、字符流、缓冲流、转换流、序列化流等

简介: 【IO】JavaIO流:字节流、字符流、缓冲流、转换流、序列化流等


Java IO


1. 认识IO

IO流

  • 流的方向划分:
  • 输入流:读取
  • 输出流:写出
  • 流操作的文件类型划分:
  • 字节流:可读取所有文件类型
  • InputStream:字节输入流
  • OutputStream:字节输出流
  • 字符流:可读取纯文本文件
  • Reader:字符输入流
  • Writer:字符输出流




2. FileOutputStream(写)

使用步骤

  • 创建字节输出流对象
  • 参数:字符串表示的路径/File对象
  • 文件不存在,或自动创建一个新的,但需要保证父级路径存在
  • 如果文件已经存在,会被覆盖
  • 写数据
  • writer()中的参数是int类型,实际写出到文件内容是整数对应的ASCII码值
  • 三种方式:
  • void write(int b):一次写一个字节数据
  • void write(byte[] b):一次写一个字节数组的数据
  • void write(byte[] b,int off,int len):一次写一个数组的部分数据(参数:数组、起始索引、个数)
  • 释放资源
  • 每次使用完流之后都需要进行资源释放
  • 初识案例:
public class FileOutputStreamDemo {
    public static void main(String[] args) throws IOException {
        //获取输出流对象
        FileOutputStream fos = new FileOutputStream("D:\\JavaData\\myIO\\a.txt");
        //写操作
        fos.write(97);
        //关闭资源
        fos.close();
    }
}
  • 换行符:
  • Windows:\r\n
  • Linux:\n
  • Mac:\r
  • 续写:
  • 当写出的文件存在时,一般情况会对内容进行覆盖,若想续写,需要在创建文件输出流对象时设置参数。
//参数一:路径
//参数二:是否续写:true续写   false:覆盖
FileOutputStream fos = new FileOutputStream("D:\\JavaData\\myIO\\a.txt",true);




3. FileInputStream(读)

使用步骤

  • ①创建字节输入流对象
  • 如果读取文件不存在,直接报错FileNotFoundException
  • ②读取数据
  • 一次读一个字节,读出内容是数据在ASCII码对应的int数字
  • 读到文件末尾,read()返回 -1
  • public int read():一次读取一个字节数据
  • public int read(byte[] buffer):一次读取一个字节数组数据
  • ③释放资源
  • 每次使用完流必须进行资源释放

  • 避免乱码:
  1. 不使用字节流读取文本文件
  2. 编码、解码时使用同一个码表,同一个编码方式


循环读取

  • 示例:
  • 一次读取一个字节
public class FileInputStreamDemo {
    public static void main(String[] args) throws IOException {
        //创建文件输入流对象
        FileInputStream fis = new FileInputStream("D:\\JavaData\\myIO\\a.txt");
        //循环读取(一次读取一个字节)
        int b;
        while((b = fis.read()) != -1){
            System.out.print((char)b);
        }
        //释放资源
        fis.close();
    }
}




4. Java编码和解码

Java中的编码和解码方式

  • 编码:
  • public byte[] getBytes():使用默认方式编码
  • public byte[] getBytes(String charsetName):使用指定的方式进行编码
  • 解码:
  • String(byte[] bytes):只用默认方式进行解码
  • String(byte[] bytes,String charsetName):使用指定的方式进行解码




5. 字符流

字符流

  • 字符流 : 字节流 + 字符集
  • 特点
  • 输入流:一次读一个字节,遇到中文,一次读多个字节
  • 输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写入文件
  • 适用于:对纯文本文件进行读写操作。


1) FileReader

使用步骤

  • ①创建字符输入流对象
  • public FileReader(File file):创建字符输入流关联本地文件
  • publlic FileReader(String pathname):创建字符输入流关联本地文件
  • 若文件不存在,报错
  • ②读取数据
  • public int read():读取数据,都到末尾返回 -1
  • public int read(char[] buffer):一次读取数组长度的数据,读取到末尾返回 -1
  • 空参方法,按照字节进行读取,读取中文时一次读取多个字节,读取后解码,返回一个整数。
  • 读取到文件末尾,read()返回 -1
  • ③释放资源
  • public int close():释放/关闭资源

  • 原理
  • 创建字符流对象时:底层关联文件,并创建缓冲区(长度为8192的数组)
  • 读取数据时:
  1. 判断缓冲区是否有数据可以读取、
  2. 缓冲区没数据,从文件中获取数据并写入缓冲区,每次尽可能装满缓冲区,若文件也没有数据,返回 -1
  3. 缓冲区有数据,直接读取缓冲区
  4. 空参read() —— 一次读取一个字节,中文则一次读取多个字节,把字节解码并转换成十进制
  5. 带参read() —— 把读取字节、解码、强转三步合并,转换后的字符存入字符数组中


2)FileWriter

使用

  • ①创建字符输出流对象
  • public FileWriter(File file):创建字符输出流关联本地文件
  • public FileWriter(String pathname):创建字符输出流关联本地文件
  • public FileWriter(File file,boolean append)续写方式,创建字符输出流关联本地文件
  • public FileWriter(String pathname,boolean append)续写方式,创建字符输出流关联本地文件
  • 如果文件不存,自动创建新文件,但需要保证父级路径存在。
  • 如果文件存在,会进行覆盖,需要传入参数,若无需覆盖可以打开续写开关(true)。
  • ②写出数据:
  • void write(int c):写出一个字符(输出整数对应ASCII码)
  • void write(String s):写出一个字符串
  • void write(String str,int off,int len)写出一个字符串,指定起始索引和输出长度
  • void write(char[] cbuf):写出一个字符数组的数据
  • void write(char[] cbuf,int off,int len):写出一个字符数组的数据,指定起始索引和输出长度
  • ③关闭资源
  • 关闭前将缓冲区数据写入文件
  • 缓冲区可以手动刷新flush() —— 缓冲区数据写入文件、并清空缓冲区




6. 缓冲流

缓冲流

  • 缓冲流
  • ①字节缓冲流
  • 1)BufferedInputStream —— 字节缓冲输入流
  • 2)BufferedOutputStream —— 字节缓冲输出流
  • ②字符缓冲流
  • 1)BufferedReader —— 字符缓冲输入流
  • 2)BufferedWriter —— 字符缓冲输出流


1)字节缓冲流

字节缓冲流

  • 使用:
  • public BufferedInputStream(InputStream is):把基本流包装成高级流,提高读取数据的效率
  • public BufferedOutoutStream(OutputStream os):把基本流包装成高级流,提高写出数据的效率
  • 原理:
  • 底层自带长度为8192长度字节数组的缓冲区(8KB)提高性能。
  • 字节流自身不带缓冲区,缓冲流能够显著提高性能


2)字符缓冲流

字符缓冲流

  • 使用
  • public BufferedReader(Reader r):把基本流包装成高级流,提高读取数据的效率(字符缓冲输入流对象)
  • public BufferedWriter(Writer r):把基本流包装成高级流,提高写出数据的效率(字符缓冲输出流对象)
  • 底层自带一个长度为8192字符数组的缓冲区(16KB)提升性能(缓冲区数据在内存中使用,速度快)
  • 字符流自带缓冲区,缓冲流对字符流效率提升不明显,但字符缓冲流对字符流的主要意义在于:readLine() 和 newLine()
  • 字符缓冲输入流 特有方法:
  • public String readLine():读取一行数据,读至末尾没有数据就返回null
  • 字符缓冲输出流 特有方法:
  • public void newLine():换行操作,可跨平台




7. 转换流(字符流的一种)

转换流

  • 转换流:是字符流和字节流之间的桥梁。
  • InputStreamReader —— 字节转换输入流
  • public InputStreamReader(InputStream in):将字节输入流转换为字符输入流。
  • OutputStreamWriter —— 字节转换输出流
  • public OutputStreamWriter(OutputStream out):将字符输出流转换为字节输出流。
  • 作用:当字节流想要使用字符流中的方法时,可使用转换流。




8. 序列化流 / 反序列化流

序列化流(对象操作输出流)

  • 作用:可以将Java对象写入到本地文件中。
  • 使用
  • 构造方法 ——public ObjectOutputStream(OutputStream out):把基本字节输出流,包装成序列化流(获取序列化流对象)
  • 成员方法 ——public final void writeObject(Object obj):把对象序列化(写出)到本地文件中去
  • 若直接使用对象输出流将对象保存到文件中时,会报错NotSerializableException需要让JavaBean类实现Serializable接口,表示此类对象是可序列化的。


反序列化流(对象操作输入流)

  • 作用:可以把序列化到本地文件中的对象,读取到程序中来。
  • 使用:
  • 构造方法 ——public ObjectInputStream(InputStream in):把基本字节输入流,包装成反序列化流(获取反序列化流对象)
  • 成员方法 ——public Object readObject():把序列化到本地文件中的对象,读取到程序中来
  • 需要让JavaBean类实现Serializable接口,表示此类对象是可序列化的。同时防止Java版本号的改变,使得序列化版本号不一致进而反序列化失败的问题,我们应该为JavaBean中手动设置一个序列化版本号:
private static final long serialVersionUID = -6357601841666449654L;




9. 打印流

打印流

  • 打印流
  • 字节打印流PrintStream
  • 字符打印流PrintWriter

  • 字节打印流-PrintStream
  • 构造方法(获取字节打印流对象):
  • public PrintStream(OutputStream/File/String):关联字节输出流/文件/文件路径
  • public PrintStream(String fileName,Charset charset):指定字符编码
  • public PrintStream(OutputStream out,boolean autoFlush):设置自动刷新
  • public PrintStream(OutputStream put,boolean aytoFlush,Charset charset):指定字符编码并自动刷新
  • 成员方法:
  • public void write(int b):将指定字节写出
  • public void println(Xxx xxx):特有方法:打印任意数据,自动刷新,自动换行
  • public void print(Xxx xxx):特有方法:打印任意数据,不换行
  • public void printf(String format,Object... args):特有方法:带有占位符地打印语句,不换行
  • 字节流底层没有缓冲区,是否开启自动刷新都没有任何变化。

  • 字符打印流-PrintWriter
  • 方法使用参考上述地字节打印流(构造方法名PrintStream 换成 PrintWriter即可、成员方法名及使用方法一致)

  • 特点:
  • 打印流仅操作文件目的地,不操作数据源,故而只能作为输出流。
  • 存在特有的写出方法,可以实现数据原样写出。
  • 存在特有的写出方法,可以实现自动刷新,自动换行(写出+刷新+换行)




10. 压缩流 / 解压缩流

解压缩流

  • **解压本质:**把压缩包中地每一个ZipEntry对象按照层级拷贝到本地的另一个文件夹中去。
  • 使用:
  • public ZipInputStream(InputStream in):构造方法,将普通字节输入流包装成解压缩流。
  • ZipInputStream.getNextEntry():获取压缩包中的entry对象,读到末尾返回null
  • 案例:
public class ZipStreamDemo {
    public static void main(String[] args) throws IOException {
        //解压缩流 示例
        //File对象,表示需要解压缩的文件
        File src = new File("D:\\JavaData\\myIO\\aa.zip");
        //File对象,表示解压后的路径
        File dest = new File("D:\\JavaData\\myIO");
        unZip(src,dest);//解压缩
    }
    //创建一个方法,用于解压
    public static void unZip(File src,File dest) throws IOException {
        //创建解压缩流对象
        ZipInputStream zip = new ZipInputStream(new FileInputStream(src));
        //读取解压后的每一个entry对象
        ZipEntry entry;
        while((entry = zip.getNextEntry()) != null){
            //如果是文件夹,解压目录下创建新的文件夹
            if(entry.isDirectory()){
                File file = new File(dest,entry.toString());
                file.mkdirs();
            }else{
                //如果是文件,输出到指定目录
                FileOutputStream fos = new FileOutputStream(new File(dest, entry.toString())); //输出流
                int i;
                while((i = zip.read()) != -1){
                    //写到目的地
                    fos.write(i);
                }
                fos.close();      //关闭输出流
                zip.closeEntry(); //关闭当前entry
            }
        }
        zip.close();
    }
}


压缩流

  • ZipOutputStream
  • 压缩单个文件:




目录
相关文章
|
5月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
2月前
|
Java
缓冲流与高效IO
为了提高IO操作的效率,Java提供了缓冲流(BufferedStream),包括BufferedInputStream、BufferedOutputStream、BufferedReader和BufferedWriter。这些缓冲流在读写操作中添加了缓冲区。
94 52
|
4月前
|
Java
缓冲流和转换流的使用【 File类+IO流知识回顾③】
这篇文章介绍了Java中缓冲流(BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter)和转换流(InputStreamReader, OutputStreamWriter)的使用,包括它们的构造方法和如何利用它们提高IO操作的效率及处理字符编码问题。
缓冲流和转换流的使用【 File类+IO流知识回顾③】
|
3月前
|
Java 数据处理 开发者
揭秘Java IO流:字节流与字符流的神秘面纱!
揭秘Java IO流:字节流与字符流的神秘面纱!
48 1
|
3月前
|
自然语言处理 Java 数据处理
Java IO流全解析:字节流和字符流的区别与联系!
Java IO流全解析:字节流和字符流的区别与联系!
116 1
|
4月前
|
移动开发 Java Linux
IO流:字节流
在Java编程中,IO流是一个核心概念,用于与文件、网络、内存等数据源交互。Java的IO库提供丰富的类和方法支持数据读写。IO流分为字节流和字符流,前者可操作所有类型文件,后者仅限纯文本文件。`FileOutputStream`用于向文件写入字节,支持多种写入方式,并可通过构造函数的布尔参数控制是否追加写入。`FileInputStream`则用于从文件读取字节,支持逐字节或批量读取。文件拷贝可通过结合读写操作实现,高效的方法是一次性读取并写入大容量数组。处理IO流时需注意异常管理,合理使用try-catch-finally结构确保资源正确释放。JDK7及以后版本提供了自动关闭资源的简化语法
58 10
|
5月前
|
XML 存储 JSON
【IO面试题 六】、 除了Java自带的序列化之外,你还了解哪些序列化工具?
除了Java自带的序列化,常见的序列化工具还包括JSON(如jackson、gson、fastjson)、Protobuf、Thrift和Avro,各具特点,适用于不同的应用场景和性能需求。
|
5月前
|
JSON Java 数据格式
【IO面试题 七】、 如果不用JSON工具,该如何实现对实体类的序列化?
除了JSON工具,实现实体类序列化可以采用Java原生序列化机制或第三方库如Protobuf、Thrift、Avro等。
|
5月前
|
存储 缓存 Java
15 Java IO流(File类+IO流+字节流+字符流+字节编码)
15 Java IO流(File类+IO流+字节流+字符流+字节编码)
60 3
|
2月前
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。