Java_字节流

一切皆为字节

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

字节输出流【OutputStream】&【FileOutPutStream】

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) 将指定的字节写入此输出流。

其中常用的子类:

  • public class FileOutputStream extends OutputStream

FileOutputStream:文件字节输出流
作用:把内存中的数据写到硬盘文件中
构造方法:

  • FileOutputStream(File file) 创建文件输出流以写入由指定的 File对象表示的文件。
  • FileOutputStream(String name) 创建文件输出流以指定的名称写入文件。

参数:写入数据的目的地
(File file):目的地是一个文件
(String name):目的地是一个文件的路径
构造方法的作用:

  1. 创建一个FileOutputStream对象
  2. 会根据构造方法中传递的文件/文件路径,创建一个空的文件
  3. 会把FileOutputStream对象指向创建好的文件

字节输出流写入数据到文件

写入数据的原理(内存->硬盘):
Java程序->JVM(Java虚拟机)->OS(操作系统)->OS调用写数据方法->把数据写到文件中
字节输出流的使用步骤:

  1. 创建一个FileOutputStream对象,构造方法中传递写入数据目的地
  2. 调用FileOutputStream中的write,把数据写到文件中
  3. 释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提供程序效率)

代码示例:

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

public class Demo01OutputStream {
  public static void main(String[] args) throws IOException {
    // 1. 创建一个FileOutputStream对象,构造方法中传递写入数据目的地
    FileOutputStream fileOutputStream = new FileOutputStream("D:\\a.txt");
    // 2. 调用FileOutputStream中的write,把数据写到文件中
    fileOutputStream.write(111);
    // 3. 释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提供程序效率)
    fileOutputStream.close();
  }
}

字节输出流写多个字节的方法

  • public void write(byte[] b):将b.length字节从指定的字节数组写入此输出流

代码实例:

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

public class Demo02OutputStream {
  public static void main(String[] args) throws IOException {
    // 1. 创建一个FileOutputStream对象,构造方法中传递写入数据目的地
    FileOutputStream fileOutputStream = new FileOutputStream("D:\\a.txt");
    // 2. 调用FileOutputStream中的write,把数据写到文件中
    byte[] bytes = {66, 67, 68};
    fileOutputStream.write(bytes);
    // 3. 释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提供程序效率)
    fileOutputStream.close();
  }
}

如果写的第一个字节是正数(0-127),那么显示的时候会查询ASCII表



如果写的第一个字节是负数,那么第一个字节会和第二个字节组成一个中文显示,查询系统默认码表(GBK)。那我们将数组中的第一个元素改为负数

byte[] bytes = {-66, 67, 68};

重新执行下方法,可以见先两个字母变成了一个汉字。注意:这不是乱码


  • public void write(byte[], int off, int len):从指定的字节数组写入len字节,从偏移量off开始输出到此输出流
    该方法可以把一部分数据写入都文件中。比如说,我只想让txt文件中显示CD两个字母,那么我们可以把off起始长度设为1,len结束长度设为2
    代码示例:
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo02OutputStream {
  public static void main(String[] args) throws IOException {
    // 1. 创建一个FileOutputStream对象,构造方法中传递写入数据目的地
    FileOutputStream fileOutputStream = new FileOutputStream("D:\\a.txt");
    // 2. 调用FileOutputStream中的write,把数据写到文件中
    byte[] bytes = {66, 67, 68, 69, 70};
    fileOutputStream.write(bytes, 1, 2);
    // 3. 释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提供程序效率)
    fileOutputStream.close();
  }
}

可以看见文件中只有CD两个字母



写入字符串的第二种方法,可以使用String类中的方法,把字符串转换为数组

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

public class Demo02OutputStream {
 public static void main(String[] args) throws IOException {
   // 1. 创建一个FileOutputStream对象,构造方法中传递写入数据目的地
   FileOutputStream fileOutputStream = new FileOutputStream("D:\\a.txt");
   // 2. 调用FileOutputStream中的write,把数据写到文件中
   byte[] bytes = "你好".getBytes();
   System.out.println(Arrays.toString(bytes));
   fileOutputStream.write(bytes);
   // 3. 释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提供程序效率)
   fileOutputStream.close();
 }
}

可见文件中显示了你好两个字


字节输出流的续写与换行

在刚在的不断地执行方法和创建文件中,我其实并没有删掉原来的文件再执行方法,这就说明了重新执行一次方法会新建一个文件,如果本来就有这个文件就会把原来的文件覆盖掉。那么如何才能不让他替换,而是继续往后写,Java给我们提供了两个方法:

追加写/续写:使用两个参数的构造方法

  • public FileOutputStream(File file, boolean append) throws FileNotFoundException:创建文件输出流以写入由指定的File对象表示的文件。如果第二个参数是true,则字节将被写入文件的末尾而不是开头。

file - 要打开的文件写入。
append - 如果是 true ,那么字节将被写入文件的末尾,而不是开头

  • public FileOutputStream(String name, boolean append) throws FileNotFoundException:创建文件输出流以指定的名称写入文件。如果第二个参数是true,则字节将写入文件的末尾而不是开头。

name - 与系统相关的文件名
append - 如果是 true ,那么字节将被写入文件的末尾,而不是开头
代码实例:

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

public class Demo03OutputStream {
  public static void main(String[] args) throws IOException {
    FileOutputStream fileOutputStream = new FileOutputStream("D:\\a.txt", true);
    fileOutputStream.write("你好".getBytes());
    fileOutputStream.close();
  }
}

连续执行两次方法,可以看见文件中出现了两个你好。



如果想要换行,需要写入换行符号,也是String类型的字符串,但是系统不一样字符串也不一样

  • windows:\n\r
  • linux/unix:/n
  • mac:/r
    代码示例:
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo03OutputStream {
    public static void main(String[] args) throws IOException {
        FileOutputStream fileOutputStream = new FileOutputStream("D:\\a.txt", true);
        for (int i = 0; i < 10; i++) {
            fileOutputStream.write("你好".getBytes());
            fileOutputStream.write("\r\n".getBytes());
        }
        fileOutputStream.close();
    }
}

接着刚才的两个你好继续


字节输入流【InputStrem】&【FileInputStream】

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

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

小贴士:当完成流的操作时,必须调用close()方法,释放系统资源。

java.io.FileInputStream:从文件系统中的文件获取输入字节。
构造方法:

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

读取数据的原理(硬盘->内存):
Java程序->JVM->OS->OS读取数据的方法->读取数据
字节输入流的使用步骤:

  1. 创建FileInputStream对象,构造方法中绑定要读取的数据源
  2. 使用FileInputStream对象中的read()方法读取文件
  3. 释放资源

代码示例:

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

public class Demo01FileInputStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fileInputStream = new FileInputStream("D:\\a.txt");//文件中只有123三个数字
        int read = fileInputStream.read();
        System.out.println(read);
        int read1 = fileInputStream.read();
        System.out.println(read1);
        int read2 = fileInputStream.read();
        System.out.println(read2);
        int read3 = fileInputStream.read();
        System.out.println(read3);
        fileInputStream.close();
    }
}
控制台打印:
49
50
51
-1

可以看到,控制台依次打印出了三个数字在ASCII表上对应的序号。因为文件中只有三个数字,所以到了第四次读取数据的时候,结果就会变成-1。
以上读取文件是一个重复的过程,所以可以使用循环优化,假如说文件中有100个数字,或者不知道有多少数据,这个时候就要用while循环来进行读取,当结果为-1的时候,说明读取完了,结束循环。先在文件中随便写入一批数据
代码示例:

public class Demo01FileInputStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fileInputStream = new FileInputStream("D:\\a.txt");
        // 记录读取到的字节
        int read = 0;
        while ((read = fileInputStream.read()) != -1) {
            System.out.print((char)read);
        }
        fileInputStream.close();
    }
}
控制台打印:
567812345567134678367878178278234782345789234578934783245

当读取返回的结果返回-1的时候,非常完美的打印出了文件的数字。

字节输入流一次输入多个字节

上面的字节输入,哪怕用的while循环,read()方法也是一个字节一个字节的输入,效率特别低。
read()方法有个有参构造

  • int read(byte[] b):从该输入流读取最多 b.length个字节的数据为字节数组。

该方法中的byte[]有什么作用?返回值int是什么?带着问题一块看下面的代码:

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容