Java基础 第四节 第十二课

举报
我是小白呀iamarookie 发表于 2021/09/09 22:46:32 2021/09/09
【摘要】 字节流 一切皆为字节字节输出流 (OutputStream)FileOutputStream 类构造方法写出字节数据写出字节 写出字节数组写出指定长度的字节数组数据追加续写写出换行注意事项 ...

一切皆为字节

一切文件数据 (文本, 图片, 视频等) 在存储时, 都是以数字的形式保存, 是一个个的字节, 那么传输时一样如此. 所以, 字节流可以传输任意文件数据. 在操作的时候, 我们要时刻明确, 无论使用什么样的流对象, 底层传输的始终为二进制数据.

字节输出流 (OutputStream)

java.io.OutputStream抽象类是表示字节输出流的所有类的超类, 将指定的字节信息写出到目的地. 它发定义了子节输出的基本功能方法:

  • public void close(): 关闭此输出流并释放与此流相关的任何系统资源
  • public void flush(): 刷新此输出流并强制任何缓冲的输出字节被写出
  • public void write(byte[] b): 将 b.length 字节指定的字节数组写入此输出流
  • public void write(byte[] b, int off, int len): 从指定的字节数组写入 len 字节, 从偏移量 off 开始输出到此输出流
  • public abstract void write(int b): 将指定的字节输出
    注: close 方法, 当完成流的操作时. 必须调用此方法, 释放系统资源.

FileOutputStream 类

OutputStran 有很多子类, 我们从最简单的一个子类开始.

```java.io.FileOutputStream``类是文件输出流, 用于将数据写出到文件.

构造方法

public FileOutputStream(File file): 创建文件输出流以写入由指定的 File 对象表示的文件
public FileOutputStream(String name): 创建文件输出流以指定的名称写入文件
当创建一个流对象时, 必须传入一个文件路径. 该路径下, 如果没有这个文件, 会创建该文件. 如果有这个文件, 会清空这个文件的数据.

构造举例, 代码如下:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class Test {
    public static void main(String[] args) throws FileNotFoundException {
        // 使用File对象创建流对象
        File file = new File("a.txt");
        FileOutputStream fos1 = new FileOutputStream(file);

        // 使用文件名创建流对象
        FileOutputStream fos2 = new FileOutputStream("b.txt");
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

写出字节数据

写出字节

写出字节: write(int b)方法, 每次可以写出一个字节数据. 代码使用演示:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("a.txt");
        // 写出数据
        fos.write(97);  // 写出第1个字节
        fos.write(98);  // 写出第2个字节
        fos.write(99);  // 写出第3个字节
        // 关闭资源
        fos.close();
    }
}

输出结果:
abc

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

注:
虽然参数为 int 类型四个字节, 但是只会保留一个字节的信息写出.
流操作完毕后, 必须释放系统资源. 调用 close 方法, 千万记得.

写出字节数组

写出字节数组: write(byte[] b), 每次可以写出数组中的数据, 代码使用演示:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("a.txt");
        // 字符串转换为字节数组
        byte[] b = "程序员".getBytes();
        // 写出字节数组数据
        fos.write(b);
        // 关闭资源
        fos.close();
    }
}

输出结果:
程序员

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

写出指定长度的字节数组

写出指定长度字节数组:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        // 使用文件名创建流对象
        FileOutputStream fos = new FileOutputStream("a.txt");
        // 字符串转换为字节数组
        byte[] b = "abcde".getBytes();
        // 写出从索引2开始, 2个字节. 索引2是c, 两个字节, 也就是cd
        fos.write(b,2,2);
        // 关闭资源
        fos.close();
    }
}

输出结果:
cd

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

数据追加续写

经过以上的演示, 每次程序运行, 创建输出流对象, 都会清空目标文件中的数据. 如何保留目标文件中的数据, 还能继续添加数据呢?

  • public FileOutputStream(File file, boolean append): 创文件输出流以写入由指定的 File 对象表示文件
  • public FileOutputStream(String name, boolean append): 文件输出流指定的名称写入文件

这两个构造方法, 参数中都需要传入一个 boolean 类型的值. true 表示追加数据, flase 表示清空原有数据. 这样创建的输出流对象, 就可以指定是否追加续写了, 代码使用演示:

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

public class Test {
    public static void main(String[] args) throws IOException {
        // 使用文件名创建流对象
        FileOutputStream fos = new FileOutputStream("a.txt",true);
        // 字符串转换为字节数组
        byte[] b = "abcde".getBytes();
        // 写出字节数组数据
        fos.write(b);
        // 关闭资源
        fos.close();
    }
}

输出结果:
文件操作前:cd
文件操作后:cdabcde

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

写出换行

Windows 系统里, 换行符号是 \r\n. 可以指定是否换行.

代码展示:

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

public class Test8 {
    public static void main(String[] args) throws IOException {
        // 使用文件名创建流对象
        FileOutputStream fos = new FileOutputStream("a.txt");
        // 定义字节数组
        byte[] words = {97,98,99,100,101};
        // 遍历数组
        for (byte word : words) {
            // 写出一个字节
            fos.write(word);
            // 写出一个换一行, 换行符号转成数组写出
            fos.write("\r\n".getBytes());
        }
        // 关闭资源
        fos.close();
    }
}

输出结果:
a
b
c
d
e

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

注意事项

回车符 \r 和换行符 \n:

  • 回车符: 回到一行的开头 ( return )
  • 换行符: 下一行 ( newline )

系统中的换行:

  • Windows 系统里, 每行结尾是 回车 + 换行, 即 \r\n
  • Unix 系统里, 每行结尾只有 换行, 即 \n
  • Mac 系统里. 每行结尾是 回车, 即 \r. 从 Mac OS X 开始与 Linux 统一

字节输入流 (InputStream)

java.io.InputStream抽象类是表示字节输入流的所有类的超类, 可以读取字节信息到内存中. 它定义了字节输入流基本共性功能方法:

  • public void close(): 关闭此输入流并释放与此相关联的任何系统资源
  • public void int read(): 从输入流读取数据的下一个字节
  • public int read(byte[] b): 从输入流中读取一些字节数, 并将它们存储到字节数组 b 中

注: close 方法, 当完成流的操作时, 必须调用此方法, 释放系统资源.

FileInputStream 类

java.io.FileInputStream类是文件输入流, 从文件中读取字节.

构造方法

  • FileInputStream(File file): 通过打开与实际文件的连接来创建一个 FileInputStream, 该文件由文件系统中的 File 对象 file 命名.
  • FileInputStream(String name): 通过打开与实际文件的连接来创建一个 FileInputStream, 该文件由文件系统路径名 name 命名.

当你创建一个流对象时, 必须传入一个文件的路径. 该路径下, 如果没有该文件, 会抛出FileNotFoundExption.

代码展示:

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

public class Test {
    public static void main(String[] args) throws IOException {
        // 使用File 对象创建流对象
        File file = new File("a.txt");
        FileInputStream fis1 = new FileInputStream(file);

        // 使用文件名称创建流对象
        FileInputStream fis2 = new FileInputStream("a.txt");
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

读取字节数据

读取字节

读取字节: read 方法, 每次可以读取一个字节的数据, 提升为 int 类型. 读取到文件末尾, 返回 -1. 代码展示:

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

public class Test {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileInputStream fis = new FileInputStream("read.txt");
        // 读取数据, 返回一个字节
        int read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        // 读取到末尾, 返回-1
        read = fis.read();
        System.out.println(read);
        // 关闭资源
        fis.close();
    }
}

输出结果:
a
b
c
d
e
-1

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

循环改进读取方式, 代码使用演示:

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

public class Test {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileInputStream fis = new FileInputStream("read.txt");
        // 定义变量, 保存数据
        int b;
        // 循环读取
        while ((b = fis.read()) != -1 ){
            System.out.println((char)b);
        }
        // 关闭资源
        fis.close();
    }
}
输出结果:
a
b
c
d
e

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

注:

  • 虽然读取了一个字节, 但是会自动提升为 int 类型.
  • 流操作完毕后, 必须释放系统资源, 调用 close 方法, 千万记得

使用字节数组读取

使用字节数组读取: read(byte[] b), 每次读取 b 的长度个字节到数组中, 返回读取到的有效字节个数. 读取到末尾时, 返回 -1. 代码展示:

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

public class Test {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileInputStream fis = new FileInputStream("read.txt");  // 文件中为abcde
        // 定义变量. 作为有效个数
        int len;
        // 定义字节数组, 作为装字节数据的容器
        byte[] b  = new byte[2];
        // 循环读取
        while ((len = fis.read(b)) != -1) {
            // 每次读取后, 把数组编程字符串打印
            System.out.println(new String(b));
        }
        // 关闭资源
        fis.close();
    }
}

输出结果:
ab
cd
ed

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

错误数据 d, 是由于最后一次读取时, 只读取一个字节 e. 数组中, 上次读取的数据没有被完全替换, 所以要通过 len, 获取有效的字节, 代码使用展示:

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

public class Test13 {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileInputStream fis = new FileInputStream("read.txt");
        // 定义变量, 作为有效个数
        int len;
        // 定义字节数组, 作为装字节数据的容器
        byte[] b = new byte[2];
        // 循环读取
        while ((len = fis.read(b)) != -1) {
            // 每次读取后, 把数组变成字符串打印
            System.out.println(new String(b,0,len));  // len: 每次读取的有效字节个数
        }
        // 关闭资源
        fis.close();
    }
}

输出结果:
ab
cd
e

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

注: 使用数组读取, 每次读取多个字节, 减少了系统间的 IO 操作次数. 从而提高了读写的效率, 建议开发中使用.

字节流练习: 图片复制

复制原理图解

在这里插入图片描述

案例实现

复制图片文件, 代码使用演示:

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

public class Test14 {
    public static void main(String[] args) throws IOException {
        // 创建流对象
        // 指定数据源
        FileInputStream fis = new FileInputStream("C:/Users/Windows/Pictures/OIP.jpg");
        // 指定目的地
        FileOutputStream fos = new FileOutputStream("copy.jpg");

        // 定义数组
        byte[] b = new byte[1024];
        // 定义长度
        int len;
        // 循环读取
        while ((len = fis.read(b)) != -1) {
            // 写出数据
            fos.write(b,0,len);
        }
        fos.close();
        fis.close();
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

执行结果:
在这里插入图片描述
注: 流的关闭原则: 先开后关, 后开先关.

文章来源: iamarookie.blog.csdn.net,作者:我是小白呀,版权归原作者所有,如需转载,请联系作者。

原文链接:iamarookie.blog.csdn.net/article/details/110385463

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。