【从零开始学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);
        }
相关推荐
范什么特西12 分钟前
计算机杂记
java
RyFit20 分钟前
SpirngAI
java
庞轩px26 分钟前
第六篇:Spring用了哪些设计模式?——从单例到代理,拆解框架中的经典设计
java·spring·设计模式·bean·代理模式·aop·单例
神仙别闹30 分钟前
基于 C# OpenPGP 的文件管理系统
开发语言·c#
番石榴AI1 小时前
纯 CPU 推理!0.1B 超轻量级端到端OCR模型,使用 Java 进行文档解析
java·开发语言·ocr
likerhood1 小时前
ConcurrentHashMap详细讲解(java)
java·开发语言·性能优化
机器学习之心1 小时前
集成BWM法、熵权法、改进博弈论组合赋权与三角直觉模糊云模型的多属性评价模型,MATLAB代码
开发语言·matlab·熵权法·三角直觉模糊云模型·bwm法·改进博弈论组合赋权·多属性评价模型
特种加菲猫2 小时前
二叉搜索树:数据世界的“快速寻路指南”
开发语言·c++
特种加菲猫2 小时前
STL关联容器:Set/Multiset与Map/Multimap详解
开发语言·c++
我滴老baby2 小时前
0基础速通Python+AI|2026热门轻量化玩法全攻略:从入门到实战,3天搞定AI应用开发
开发语言·人工智能·python