【从零开始学Java | 第三十五篇】IO流-字节流

目录

前言

一、IO流的分类

1.字节输出流(FileOutputStream)

①基本用法

②写数据的三种方式

③换行和续写

2.字节输入流(FileInputStream)

①FileInputStream的循环读取

3.练习:文件拷贝

①解决文件拷贝速度慢的方式


前言

在Java开发中,如果我们需要读取本地配置文件、上传下载图片,还是进行网络通信,都离不开一个核心概念------I/O 流(Input/Output Stream)

一、IO流的分类

| 类别 | 读数据(输入流) | 写数据(输出流) | 适用场景 |
| 字节流 (Byte) | InputStream | OutputStream | 处理所有类型的文件(图片、音频、视频、压缩包等)。它是万能的,底层都是按字节(8 bit)传输。 |

字符流 (Character) Reader Writer 专门用来处理纯文本文件(.txt、.java、.xml 等)。它在底层做了字符编码的转换,避免了中文乱码。

指南:如果你不知道文件是什么类型,或者要拷贝图片、音频,无脑用字节流 。如果你确定要处理的是纯文本,且需要按行读取,强烈建议用字符流

1.字节输出流(FileOutputStream)

操作本地文件的字节输出流,可以把程序中的数据写到本地文件中。

步骤:

  1. 创建字节输出流对象
    • 细节1:参数表示的路径可以是字符串或者File对象
    • 细节2:如果文件不存在,在执行方法后会新建一个文件,但是要保证父级路径是存在的
    • 细节3:如果文件已经存在,则会清空文件,写入程序的内容;如果想要接着写,要将FileOutPutStream的第二个参数append设置为true。
  2. 写数据
  3. 释放资源
    • 每次使用完流之后都要释放资源。

①基本用法

复制代码
FileOutputStream fos = new FileOutputStream("src\\a.txt");
fos.write(97);
fos.close();

②写数据的三种方式

| 方法 | 说明 |
| void write(int b) | 一次写一个字节的数据 |
| void write(byte[] b) | 一次写一个字节数组的数据 |

void write(byte[] b, int off, int len) 一次写一个字节数组的部分数据

③换行和续写

换行:

复制代码
FileOutputStream fos = new FileOutputStream("src\\a.txt");
String str1 = "hello Java";
byte[] bytes1 = str1.getBytes();
fos.write(bytes1);

String wrap = "\\r\\n";
byte\[\] bytes2 = wrap.getBytes();
fos.write(bytes2);

String str2 = "Bye Java";
byte[] bytes3 = str2.getBytes();
fos.write(bytes3);
fos.close();

续写:

将FileOutPutStream的第二个参数append设置为true。

复制代码
FileOutputStream fos = new FileOutputStream("src\\\\a.txt",true);
String str1 = "continue hello Java";
byte[] bytes1 = str1.getBytes();
fos.write(bytes1);

String wrap = "\r\n";
byte[] bytes2 = wrap.getBytes();
fos.write(bytes2);

String str2 = "Continue Bye Java";
byte[] bytes3 = str2.getBytes();
fos.write(bytes3);
fos.close();

2.字节输入流(FileInputStream)

操作本地文件的字节输入流,可以把本地文件中的数据读取到程序中来。

步骤:

  1. 创建字节输入流对象
    • 细节1:如果文件不存在,直接报错。
  2. 读数据
    • 细节1:一次读一个字节,读出的是数据在ASCII上对应的数字。
    • 细节2:读到文件数据的末尾,read会返回-1。
  3. 释放资源
    • 每次使用完流之后都要释放资源。

①FileInputStream的循环读取

由于read读到文件数据的末尾时会返回-1,因此可以将该条件作为循环读取结束的条件。

由于读取的是数据的ASCII数字,因此可以使用数据类型的强转。

最后记得释放资源。

复制代码
FileInputStream fis = new FileInputStream("src\\a.txt");
int b = 0;
while((b = fis.read()) != -1){
    System.out.print((char)b);
}
fis.close();

3.练习:文件拷贝

核心思想:边读边写。

细节:先开的流永远最后释放资源。

该方法只能实现小文件的拷贝。

原因:该方法实现原理是一个字节一个字节的读取。

复制代码
public class Test {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("src\\a.txt");
        FileOutputStream fos = new FileOutputStream("src\\a_copy.txt");
        int b;
        while((b = fis.read()) != -1){
            fos.write(b);
        }

        fos.close();
        fis.close();
    }
}

①解决文件拷贝速度慢的方式

可以通过FileInputStream 中的 read(byte[] buffer)重载的方法,实现读取多个字节。

通常这个buffer数组的大小为1024的整数倍,建议一次读5MB(1024 *1024 *5)。

java 复制代码
        FileInputStream fis = new FileInputStream("src\\a.txt");
        byte[] bytes = new byte[2];

        int len1 = fis.read(bytes);
        System.out.println(len1);
        String str1 = new String(bytes);
        System.out.println(str1);


        int len2 = fis.read(bytes);
        System.out.println(len2);
        String str2 = new String(bytes);
        System.out.println(str2);

        int len3 = fis.read(bytes);
        System.out.println(len3);
        String str3 = new String(bytes);
        System.out.println(str3);

        int len4 = fis.read(bytes);
        System.out.println(len4);
        String str4 = new String(bytes);
        System.out.println(str4);

Q1:为什么读取的length为1,但是打印了两个字符。

Q2:为什么length为-1了,但是还能打印出字符。

A:原因就在于当只读取到一个数据时,bytes数组只更新了第一个,而第二个还是之前存留的值;当没有数据读取时,length会输出-1,但是bytes数组因为没有读取到数据因此没有更新,还是之前存留的值。

改进:

我们可以使用得到的len长度变量来限制输出的长度。

java 复制代码
public class Test {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("src\\a.txt");
        byte[] bytes = new byte[2];

        int len1 = fis.read(bytes);
        System.out.println(len1);
        String str1 = new String(bytes, 0, len1);
        System.out.println(str1);


        int len2 = fis.read(bytes);
        System.out.println(len2);
        String str2 = new String(bytes, 0, len2);
        System.out.println(str2);

        int len3 = fis.read(bytes);
        System.out.println(len3);
        String str3 = new String(bytes, 0, len3);
        System.out.println(str3);

文件拷贝改进:

java 复制代码
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("src\\a.txt");
        FileOutputStream fos = new FileOutputStream("src\\b.txt");

        int len;
        byte[] bytes = new byte[1024];
        while((len = fis.read(bytes)) != -1){
            fos.write(bytes, 0, len);
        }
相关推荐
逍遥德1 天前
Java 锁(线程间)和数据库锁(事务间)对比详解
java·数据库·sql·高并发·锁机制
沐雪轻挽萤1 天前
10. C++17新特性-保证的拷贝消除 (Guaranteed Copy Elision / RVO)
开发语言·c++
gwjcloud1 天前
Docker详解
java·docker·容器
河阿里1 天前
Java-JWT令牌技术深度指南
java·开发语言
WiChP1 天前
【V0.1B6】从零开始的2D游戏引擎开发之路
java·log4j·游戏引擎
leaves falling1 天前
C/C++ 的内存管理,函数栈帧详讲
java·c语言·c++
文静小土豆1 天前
Java 应用上 K8s 全指南:从部署到治理的生产级实践
java·开发语言·kubernetes
西西弗Sisyphus1 天前
Python 在终端里彩色打印
开发语言·python·print·彩色打印
zhimingwen1 天前
初探 Java 後端開發:解決 macOS 環境下 Spring Boot 項目啟動的各類「坑」
java·spring boot
Rsun045511 天前
3、Java 工厂方法模式从入门到实战
java·开发语言·工厂方法模式