• InputStream 是 Java 所有字节输入流类的父类,
  • OutputStream 是 Java 所有字节输出流类的父类,

它们都是一个抽象类,因此继承它们的子类要重新定义父类中的抽象方法。

下面首先介绍上述两个父类提供的常用方法,然后介绍如何使用它们的子类输入和输出字节流,包括 ByteArrayInputStream 类ByteArrayOutputStream 类FileInputStream 类FileOutputStream 类

字节输入流

InputStream 类及其子类的对象表示字节输入流,InputStream 类的常用子类如下。

  • ByteArrayInputStream 类:将字节数组转换为字节输入流,从中读取字节。
  • FileInputStream 类:从文件中读取数据。
  • PipedInputStream 类:连接到一个 PipedOutputStream(管道输出流)。
  • SequenceInputStream 类:将多个字节输入流串联成一个字节输入流。
  • ObjectInputStream 类:将对象反序列化。

使用 InputStream 类的方法可以从流中读取一个或一批字节。表 1 列出了 InputStream 类的常用方法。

方法名及返回值类型 说明
int read() 从输入流中读取一个 8 位的字节,并把它转换为 0~255 的整数,最后返回整数。如果返回 -1,则表示已经到了输入流的末尾。为了提高 I/O 操作的效率,建议尽量使用 read() 方法的另外两种形式
int read(byte[] b) 从输入流中读取若干字节,并把它们保存到参数 b 指定的字节数组中。 该方法返回读取的字节数。如果返回 -1,则表示已经到了输入流的末尾
int read(byte[] b, int off, int len) 从输入流中读取若干字节,并把它们保存到参数 b 指定的字节数组中。其中,off 指定在字节数组中开始保存数据的起始下标;len 指定读取的字节数。该方法返回实际读取的字节数。如果返回 -1,则表示已经到了输入流的末尾
void close() 关闭输入流。在读操作完成后,应该关闭输入流,系统将会释放与这个输入流相关的资源。注意,InputStream 类本身的 close() 方法不执行任何操作,但是它的许多子类重写了 close() 方法
int available() 返回可以从输入流中读取的字节数
long skip(long n) 从输入流中跳过参数 n 指定数目的字节。该方法返回跳过的字节数
void mark(int readLimit) 在输入流的当前位置开始设置标记,参数 readLimit 则指定了最多被设置标记的字节数
boolean markSupported() 判断当前输入流是否允许设置标记,是则返回 true,否则返回 false
void reset() 将输入流的指针返回到设置标记的起始处

注意:在使用 mark() 方法和 reset() 方法之前,需要判断该文件系统是否支持这两个方法,以避免对程序造成影响。
1.FileInputStream​(File file)

FileInputStream​(File file) 的构造方法

FileInputStream​(File file) 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。
FileInputStream​(FileDescriptor fdObj) 通过使用文件描述符 fdObj创建 FileInputStream ,该文件描述符表示与文件系统中的实际文件的现有连接。
FileInputStream​(String name) 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。

例子:

import java.io.FileInputStream;
import java.io.IOException;public class  Test{//打开文件,一次读取刚刚好内容的字节public static void readFile() throws IOException{FileInputStream fis=new FileInputStream("E:\\Hello.txt");//available()返回从此输入流中可以读取(或跳过)的剩余字节数的估计值,而不会被下一次调用此输入流的方法阻塞。byte[] buf=new byte[fis.available()];fis.read(buf);System.out.println(new String(buf));fis.close();}//打开文件,一次读取多个字节public static void readFiles() throws IOException{FileInputStream fis=new FileInputStream("E:\\Hello.txt");byte[] buf=new byte[1024];int len=0;while((len=fis.read())!=-1){System.out.println(new String(buf,0,len));}fis.close();}//打开文件,一次读取一个字节public static void OneReadFile() throws IOException{FileInputStream fis=new FileInputStream("E:\\Hello.txt");int ch=0;while((ch=fis.read())!=-1){System.out.print((char)ch);}fis.close();}public static void main(String[] args) throws IOException{OneReadFile();}
}

字节输出流

OutputStream 类及其子类的对象表示一个字节输出流。OutputStream 类的常用子类如下。

  • ByteArrayOutputStream 类:向内存缓冲区的字节数组中写数据。
  • FileOutputStream 类:向文件中写数据。
  • PipedOutputStream 类:连接到一个 PipedlntputStream(管道输入流)。
  • ObjectOutputStream 类:将对象序列化。

利用 OutputStream 类的方法可以从流中写入一个或一批字节。表 2 列出了 OutputStream 类的常用方法。

方法名及返回值类型 说明
void write(int b) 向输出流写入一个字节。这里的参数是 int 类型,但是它允许使用表达式,而不用强制转换成 byte 类型。为了提高 I/O 操作的效率,建议尽量使用write() 方法的另外两种形式
void write(byte[] b) 把参数 b 指定的字节数组中的所有字节写到输出流中
void write(byte[] b,int off,int len) 把参数 b 指定的字节数组中的若干字节写到输出流中。其中,off 指定字节数组中的起始下标,len 表示元素个数
void close() 关闭输出流。写操作完成后,应该关闭输出流。系统将会释放与这个输出流相关的资源。注意,OutputStream 类本身的 close() 方法不执行任何操作,但是它的许多子类重写了 close() 方法
void flush() 为了提高效率,在向输出流中写入数据时,数据一般会先保存到内存缓冲区中,只有当缓冲区中的数据达到一定程度时,缓冲区中的数据才会被写入输出流中。使用 flush() 方法则可以强制将缓冲区中的数据写入输出流,并清空缓冲区

1.FileOutputStream

FileOutputStream构造方法

FileOutputStream​(File file) 创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream​(FileDescriptor fdObj) 创建文件输出流以写入指定的文件描述符,表示与文件系统中实际文件的现有连接。
FileOutputStream​(File file, boolean append) 创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream​(String name) 创建文件输出流以指定的名称写入文件。
FileOutputStream​(String name, boolean append) 创建文件输出流以指定的名称写入文件。

例子:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;public class  Test{private static final String FileName="E:\\Hello.txt";public static void testWriter(){try {//创建文件"E:\\Hello.txt"对应的File对象File file=new File(FileName);//创建"E:\\Hello.txt"对应的FileOutputStream对象,默认是关闭"追加模式"FileOutputStream fileOut1=new FileOutputStream(file);//创建FileOutputStream对应的PrintStream,方便操作。PrintStream的写入接口更便利PrintStream out1=new PrintStream(fileOut1);//向文件写入26个字母out1.print("ABCDEFGHIJKLMNOPQRSTUVWXYZ");out1.close();//创建文件"E:\\Hello.txt"对应的FileOutputStream对象,打开追加模式FileOutputStream fileOut2=new FileOutputStream(file,true);//创建FileOutputStream对应的PrintStream,方便操作。PrintStream的写入接口更便利PrintStream out2=new PrintStream(fileOut2);//向文件写入“123456789”out2.print("123456789");out2.close();} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}/*** FileOutputStream 演示函数** 运行结果:* 在源码所在目录生成文件"file.txt",文件内容是“abcdefghijklmnopqrstuvwxyz0123456789”** 加入,我们将 FileOutputStream fileOut2 = new FileOutputStream(file, true);*       修改为 FileOutputStream fileOut2 = new FileOutputStream(file, false);* 然后再执行程序,“file.txt”的内容变成"0123456789"。* 原因是:* (01) FileOutputStream fileOut2 = new FileOutputStream(file, true);*      它是以“追加模式”将内容写入文件的。即写入的内容,追加到原始的内容之后。* (02) FileOutputStream fileOut2 = new FileOutputStream(file, false);*      它是以“新建模式”将内容写入文件的。即删除文件原始的内容之后,再重新写入。*/public static void main(String[] args) throws IOException{testWriter();}
}

字节数组输入流

ByteArrayInputStream 类可以从内存的字节数组中读取数据,该类有如下两种构造方法重载形式。

  • ByteArrayInputStream(byte[] buf):创建一个字节数组输入流,字节数组类型的数据源由参数 buf 指定。
  • ByteArrayInputStream(byte[] buf,int offse,int length):创建一个字节数组输入流,其中,参数 buf 指定字节数组类型的数据源,offset指定在数组中开始读取数据的起始下标位置,length 指定读取的元素个数。

例 1
使用 ByteArrayInputStream 类编写一个案例,实现从一个字节数组中读取数据,再转换为 int 型进行输出。代码如下:

import java.io.ByteArrayInputStream;public class Test {public static void main(String[] args) {byte[] b = new byte[] { 1, -1, 25, -22, -5, 23 }; // 创建数组ByteArrayInputStream bais=new ByteArrayInputStream(b,0,6);//创建字节流数组int i=bais.read();//从输入流中读取下一字节,并转换成int型数据while(i!=-1){ //如果不返回-1,则表示没有System.out.println("原值="+(byte)i+"\t\t\t转换为int类型="+i);i=bais.read();//获取下一个}}
}

在该示例中,字节输入流 bais 从字节数组 b 的第一个元素开始读取 4 字节元素,并将这 4 字节转换为 int 类型数据,最后返回。

提示:上述示例中除了打印 i 的值外,还打印出了 (byte)i 的值,由于 i 的值是从 byte 类型的数据转换过来的,所以使用 (byte)i 可以获取原来的 byte 数据。

该程序的运行结果如下:

原值=1   转换为int类型=1
原值=-1   转换为int类型=255
原值=25   转换为int类型=25
原值=-22   转换为int类型=234
原值=-5   转换为int类型=251
原值=23   转换为int类型=23

从上述的运行结果可以看出,字节类型的数据 -1 和 -22 转换成 int 类型的数据后变成了 255 和 234,对这种结果的解释如下:

  • 字节类型的 1,二进制形式为 00000001,转换为 int 类型后的二进制形式为 00000000 00000000
    0000000000000001,对应的十进制数为 1。
  • 字节类型的 -1,二进制形式为 11111111,转换为 int 类型后的二进制形式为 00000000 00000000
    0000000011111111,对应的十进制数为 255。

可见,从字节类型的数转换成 int 类型的数时,如果是正数,则数值不变;如果是负数,则由于转换后,二进制形式前面直接补了 24 个 0,这样就改变了原来表示负数的二进制补码形式,所以数值发生了变化,即变成了正数。

提示:负数的二进制形式以补码形式存在,例如 -1,其二进制形式是这样得来的:首先获取 1 的原码 00000001,然后进行反码操作,1 变成 0,0 变成 1,这样就得到 11111110,最后进行补码操作,就是在反码的末尾位加 1,这样就变成了 11111111。

字节数组输出流

ByteArrayOutputStream 类可以向内存的字节数组中写入数据,该类的构造方法有如下两种重载形式。

  • ByteArrayOutputStream():创建一个字节数组输出流,输出流缓冲区的初始容量大小为 32 字节。
  • ByteArrayOutputStream(int size):创建一个字节数组输出流,输出流缓冲区的初始容量大小由参数 size 指定。

ByteArrayOutputStream 类中除了有前面介绍的字节输出流中的常用方法以外,还有如下两个方法。

  • intsize():返回缓冲区中的当前字节数。
  • byte[] toByteArray():以字节数组的形式返回输出流中的当前内容。

例 2
使用 ByteArrayOutputStream 类编写一个案例,实现将字节数组中的数据输出,代码如下所示。

import java.io.ByteArrayOutputStream;
import java.util.Arrays;public class Test {public static void main(String[] args) {ByteArrayOutputStream baos=new ByteArrayOutputStream();byte[] b = new byte[] { 1, -1, 25, -22, -5, 23 }; // 创建数组baos.write(b, 0, 6);//将字节数组b中前4个字节元素写到输出流中System.out.println("数组中一共包含:"+baos.size()+"字节");//输出缓冲区中的字节数byte[] newByteArray=baos.toByteArray();//将输出流中的当前内容转换成字节数组System.out.println(Arrays.toString(newByteArray));}
}

该程序的输出结果如下:

数组中一共包含:6字节
[1, -1, 25, -22, -5, 23]

文件输入流

FileInputStream 是 Java 流中比较常用的一种,它表示从文件系统的某个文件中获取输入字节。通过使用 FileInputStream 可以访问文件中的一个字节、一批字节或整个文件。

在创建 FileInputStream 类的对象时,如果找不到指定的文件将拋出 FileNotFoundException 异常,该异常必须捕获或声明拋出。

FileInputStream 常用的构造方法主要有如下两种重载形式。

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

下面的示例演示了 FileInputStream() 两个构造方法的使用。

try {// 以File对象作为参数创建FileInputStream对象FileInputStream fis1 = new FileInputStream(new File("F:/mxl.txt"));// 以字符串值作为参数创建FilelnputStream对象FileInputStream fis2 = new FileInputStream("F:/mxl.txt");
} catch(FileNotFoundException e) {System.out.println("指定的文件找不到!");
}

例 3
假设有一个 D:\myJava\HelloJava.java 文件,下面使用 FileInputStream 类读取并输出该文件的内容。具体代码如下:

public class Test {public static void main(String[] args) {File f = new File("D:/myJava/HelloJava.java");FileInputStream fis = null;try {// 因为File没有读写的能力,所以需要有个InputStreamfis = new FileInputStream(f);// 定义一个字节数组byte[] bytes = new byte[1024];int n = 0; // 得到实际读取到的字节数System.out.println("D:\\myJava\\HelloJava.java文件内容如下:");// 循环读取while ((n = fis.read(bytes)) != -1) {String s = new String(bytes, 0, n); // 将数组中从下标0到n的内容给sSystem.out.println(s);}} catch (Exception e) {e.printStackTrace();} finally {try {fis.close();} catch (IOException e) {e.printStackTrace();}}}
}

如上述代码,在 FileInputDemo 类的 main() 方法中首先创建了一个 File 对象 f,该对象指向 D:\myJava\HelloJava.java 文件。接着使用 FileInputStream 类的构造方法创建了一个 FileInputStream 对象 fis,并声明一个长度为 1024 的 byte 类型的数组,然后使用 FileInputStream 类中的 read() 方法将 HelloJava.java 文件中的数据读取到字节数组 bytes 中,并输出该数据。最后在 finally 语句中关闭 FileInputStream 输入流。

图 1 所示为 HelloJava.java 文件的原始内容,如下所示的是运行程序后的输出内容。

D:\myJava\HelloJava.java文件内容如下:
/*
*第一个java程序
*/
public class HelloJava {// 这里是程序入口public static void main(String[] args) {// 输出字符串System.out.println("你好 Java");}
}

注意:FileInputStream 类重写了父类 InputStream 中的 read() 方法、skip() 方法、available() 方法和 close() 方法,不支持 mark() 方法和 reset() 方法。

文件输出流

FileOutputStream 类继承自 OutputStream 类,重写和实现了父类中的所有方法
FileOutputStream 类的对象表示一个文件字节输出流,可以向流中写入一个字节或一批字节。
在创建 FileOutputStream 类的对象时,如果指定的文件不存在,则创建一个新文件;如果文件已存在,则清除原文件的内容重新写入。

FileOutputStream 类的构造方法主要有如下 4 种重载形式。

  • FileOutputStream(File file):创建一个文件输出流,参数 file 指定目标文件。
  • FileOutputStream(File file,boolean append):创建一个文件输出流,参数 file
    指定目标文件,append 指定是否将数据添加到目标文件的内容末尾,如果为 true,则在末尾添加;如果为
    false,则覆盖原有内容;其默认值为 false。
  • FileOutputStream(String name):创建一个文件输出流,参数 name 指定目标文件的文件路径信息。
  • FileOutputStream(String name,boolean append):创建一个文件输出流,参数 name 和append 的含义同上。

注意:使用构造方法 FileOutputStream(String name,boolean append) 创建一个文件输出流对象,它将数据附加在现有文件的末尾。该字符串 name 指明了原文件,如果只是为了附加数据而不是重写任何已有的数据,布尔类型参数 append 的值应为 true

对文件输出流有如下四点说明:

  • 在 FileOutputStream 类的构造方法中指定目标文件时,目标文件可以不存在。
  • 目标文件的名称可以是任意的,例如 D:\abc、D:\abc.de 和 D:\abc.de.fg
    等都可以,可以使用记事本等工具打开并浏览这些文件中的内容。
  • 目标文件所在目录必须存在,否则会拋出 java.io.FileNotFoundException 异常。
  • 目标文件的名称不能是已存在的目录。例如 D 盘下已存在 Java 文件夹,那么就不能使用 Java 作为文件名,即不能使用
    D:\Java,否则抛出 java.io.FileNotFoundException 异常。

例 4
同样是读取 D:\myJava\HelloJava.java 文件的内容,在这里使用 FileInputStream 类实现,然后再将内容写入新的文件 D:\myJava\HelloJava.txt 中。具体的代码如下:

public class Test11 {public static void main(String[] args) {FileInputStream fis = null; // 声明FileInputStream对象fisFileOutputStream fos = null; // 声明FileOutputStream对象fostry {File srcFile = new File("D:/myJava/HelloJava.java");fis = new FileInputStream(srcFile); // 实例化FileInputStream对象File targetFile = new File("D:/myJava/HelloJava.txt"); // 创建目标文件对象,该文件不存在fos = new FileOutputStream(targetFile); // 实例化FileOutputStream对象byte[] bytes = new byte[1024]; // 每次读取1024字节int i = fis.read(bytes);while (i != -1) {fos.write(bytes, 0, i); // 向D:\HelloJava.txt文件中写入内容i = fis.read(bytes);}System.out.println("写入结束!");} catch (Exception e) {e.printStackTrace();} finally {try {fis.close(); // 关闭FileInputStream对象fos.close(); // 关闭FileOutputStream对象} catch (IOException e) {e.printStackTrace();}}}
}

如上述代码,将 D:\myJava\HelloJava.java 文件中的内容通过文件输入/输出流写入到了 D:\myJava\HelloJava.txt 文件中。由于 HelloJava.txt 文件并不存在,所以在执行程序时将新建此文件,并写入相应内容。

运行程序,成功后会在控制台输出“写入结束!”。此时,打开 D:\myJava\HelloJava.txt 文件会发现,其内容与 HelloJava.java 文件的内容相同
技巧:在创建 FileOutputStream 对象时,如果将 append 参数设置为 true,则可以在目标文件的内容末尾添加数据,此时目标文件仍然可以暂不存在。

1.6 Java字节流的使用:字节输入/输出流、文件输入/输出流、字节数组输入/输出流相关推荐

  1. 字节流转化为文件流_字节流转成字符串之后,在通过字符串转成字节流后的文件为什么会不一样?...

    public static void main(String[] args) throws Exception { File sourceFile = new File("/home/joy ...

  2. 系统学习JAVA第十七天(字节流、字符流、缓冲的字节流、缓冲的字符流、将字节流转换为缓冲的字符流、面向对象——>字节流转成对象)

    系统学习JAVA第十七天 第一阶段在2021.2.1结束了! 一.数据传输 IO输入和输出,硬盘之间的数据交换 1.文件读写流程 ①创建文件的容器 ②判断方向 合适的类 创建和文件之间的通道 ③ 调用 ...

  3. java面向字符的输入流_Java编程开发中面向字节的输入输出流

    关于面向字符的输入流和输出流方面教程已经讲解完了,下面要介绍的就是Java编程开发中面向字节的输入输出流,希望本节内容可以帮助大家更好的学习Java. 教程回顾点击查看: 字节流以字节为传输单位,用来 ...

  4. java中基本字节输出流类是_java中基本输入输出流的解释

    网络程序的很大一部分是简单的输入输出,即从一个系统向另一个系统移动字节.字节就是字节,在很大程度上,读服务器发送的数据与读取文件没什么不同:向客户传送数据与写入一个文件也没有什么区别. Java中输入 ...

  5. java字符流实际上也是字节,[Java教程]Java字节流与字符流的区别

    [Java教程]Java字节流与字符流的区别 0 2017-05-22 12:00:42 字节流与和字符流的使用非常相似,两者除了操作代码上的不同之外,是否还有其他的不同呢? 实际上字节流在操作时本身 ...

  6. [19/03/30-星期六] IO技术_四大抽象类_ 字节流( 字节输入流 InputStream 、字符输出流 OutputStream )_(含字节文件缓冲流)...

    一.概念及分类 InputStream(输入流)/OutputStream(输出流)是所有字节输入输出流的父类 [注]输入流和输出流的是按程序运行所在的内存的角度划分的 字节流操作的数据单元是8的字节 ...

  7. 1.8 Java字节流和字符流的区别,如何区分输入流和输出流?

    Java字节流和字符流的区别 首先我们先大概总结一下前面学习的内容,可分为以下几点: 以 Stream 结尾都是字节流,Reader 和 Writer 结尾都是字符流. InputStream 是所有 ...

  8. 1.7 Java字符流的使用:字符输入/输出流、字符文件和字符缓冲区的输入/输出流

    尽管 Java 中字节流的功能十分强大,几乎可以直接或间接地处理任何类型的输入/输出操作,但利用它却不能直接操作 16 位的 Unicode 字符.这就要用到字符流.本节将重点介绍字符流的操作. 字符 ...

  9. 字节流转化为文件流_JAVA IO分析一:File类、字节流、字符流、字节字符转换流...

    因为工作事宜,又有一段时间没有写博客了,趁着今天不是很忙开始IO之路:IO往往是我们忽略但是却又非常重要的部分,在这个讲究人机交互体验的年代,IO问题渐渐成了核心问题. 一.File类 在讲解File ...

最新文章

  1. 2018-3-7 HDFS架构
  2. 【Tiny4412】Tiny4412编译和烧写uboot
  3. C++ int转string的几种方法比较
  4. java trim()函数_Java - split()函数和trim()函数的使用方法
  5. 如何成为一名有效的软件工程师
  6. Delphi纯代码连SQLite数据库,同时支持数据库的加密解密
  7. android服务绑定异步,Android中异步类AsyncTask用法总结
  8. c语言函数的参数是结构变量,何去运用结构体变量和结构的变量的指针作为函数的参数...
  9. 使用C++模板判断两个类型是否一样
  10. 阿里云存储掌门人吴结生:微秒存储时代,阿里云凭什么领跑!
  11. 这个时代再也难出现贵子
  12. 重装系统时的硬盘格式化
  13. 神奇的三门问题,到底换不换门
  14. windows系统IP地址、localhost、127.0.0.1 、0.0.0.0和 本机IP区别
  15. Q版京剧脸谱来喽——花旦
  16. React技术栈探究-Redux
  17. 【Maven】你好,Maven >>> 与Maven的初次见面~
  18. android 唱歌评分系统,抖音上唱歌评分的软件叫什么 可以评分的唱歌软件推荐
  19. 隆重推荐:外星人就在月球背面
  20. 第三方分享和登录时assets目录下ShareSDK.xml

热门文章

  1. ML之FE:数据处理—特征工程的简介、使用方法、案例应用之详细攻略
  2. OS_CORE.C(5)
  3. 一个5位数,判断它是不是回文数。即12321是回文数,个位与万位相同,十位与千位相同。...
  4. YARN中的失败分析
  5. 29-分数求模(逆元)
  6. 面向对象编程(OOP)和面向过程编程
  7. 10分钟开始.Net Core
  8. 使用@required注解完成依赖检查
  9. 【BZOJ2115】[Wc2011] Xor 高斯消元求线性基+DFS
  10. hive中,向map类型插入数据时,需要str_to_map一下