[Java开发之路](8)输入流和输出流

简介:


1. Java流的分类

按流向分:
输入流:  可以从其中读入一个字节序列的对象称作输入流
输出流:  可以向其中写入一个字节序列的对象称作输出流

这些字节序列的来源地和目的地可以是文件,而且通常都是文件,但是也可以是网络连接,甚至是内存块。抽象类InputStream和OutputStream构成了输入和输出类层结构的基础。

按数据传输单位分:
字节流: 以字节为单位传输数据的流
字符流: 以字符为单位传输数据的流

按功能分:
节点流: 用于直接操作目标设备的流
过滤流: 是对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。

2. 读写字节( InputStream和OutputStream)

(1)InputStream类有一个抽象方法:
   
   
abstract int read()
这个方法将读入一个字节,并返回读入的字节,或者在遇到输入源结尾时返回-1。在设计具体的输入流时,必须覆盖这个方法以提供适用的功能,例如,在FileInputStream类中,这个方法将从某个文件中读入一个字节。

InputStream类还有若干个非抽象的方法,它们可以读入一个字节数组,或者跳过大量的字节。这些方法都要调用抽象的read方法,因此各个子类都只需覆盖一个方法。

(2)OutputStream类定义了下面的抽象方法:
   
   
abstract void write(int b)
它可以向某个输出位置写出一个字节。

(3) read和write方法在执行时都将阻塞直至字节确实被读入或写出。这就意味着如果流不能被立即访问(通常因为网络连接忙),那么当前的线程将被阻塞。这使得在这两个方法等待指定流变为可用的这段时间内,其他的线程就有机会去执行有用的工作。

当你完成对流的读写时,应该通过调用close方法来关闭它,这个调用会释放掉十分有限的操作系统资源。如果一个应用程序打开了过多的流而没有关闭,那么系统资源将被耗尽。关闭一个输出流的同时还会 冲刷用于该输出流的 缓冲区所有被临时置于缓冲区中,以便用更大的包的形式传递的字符在关闭输出流时都将被送出。如果不关闭文件,那么写出的字节的最后一个包可能将永远也得不到传递。我们可以使用flush方法认为的冲刷这些输出。

即使某个流类提供了使用 原生的read和write功能的某些具体方法,应用系统的程序员还是很少使用它们,因为大家感兴趣的数据可能包含数字,字符串和对象,而不是原生字节。

Java提供了众多从基本InputStream和OutputStream类导出的类,这些类使我们可以处理那些以常用格式表示的数据,而不只是字节。

3.流家族

流家族中的成员按照它们的使用方法进行划分,形成了处理字节和字符的两个单独的层次结构。Java中字符是采用Unicode标准,一个字符是16位,即一个字符使用两个字节来表示。因此JAVA才引入字符流。

java.io包中包含了流式I/O所需要的所有类。在java.io包中有四个基本类:InputStream、OutputStream及Reader、Writer类,它们分别处理字节流和字符流。

输入/输出 字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer

字节方面:InputStream和OutputStream类读写单子个字节或字节数组。要想读写字符串和数字,就需要功能更强大的子类,例如,DataInputStream和DataOutputStream可以以二进制格式读写所有的基本Java类型。

字符方面:对于Unicode文本,可以使用抽象类Reader和Writer的子类。 Reader和Writer类的基本方法与 InputStream和OutputStream中的方法类似。


4 字节流InputStream和OutputStream



4.1 InputStream抽象类

InputStream 为字节输入流,它本身为一个抽象类,必须依靠其子类实现各种功能,此抽象类是表示字节输入流的所有类的超类。 继承自InputStream  的流都是向程序中输入数据的,且数据单位为字节(8bit);

InputStream是输入字节数据用的类,所以InputStream类提供了3种重载的read方法。Inputstream类中的常用方法: 

常用方法 描述
public abstract int read( ) 从输入流中读取下一个字节数据。返回字节使用高位补0的int类型值表示(0-255),若返回值为-1说明没有读取到任何字节,输入流达到尽头。
public int read(byte b[ ]) 从输入流中读取b.length个字节的数据放到字节数组b中。返回值是读取的字节数。如果字节数组的长度为0,不会读取任何字节数据,返回0,否则至少尝试去读取一个字节的数据。如果没有获取到字节数据,表示流到达文件末尾,返回-1。第一个读取的字节存储在b[0],以此类推。
public int read(byte b[ ], int off, int len) 从输入流中读取至多len个字节的数据放到字节数组b中。返回值是读取的实际字节数。如果字节数组的长度为0,不会读取任何字节数据,返回0,否则至少尝试去读取一个字节的数据。如果没有获取到字节数据,表示流到达文件末尾,返回-1。第一个读取的字节存储在b[off],下一个存储在b[off+1],以此类推。
public int available( ) 返回输入流中可以读取的字节数。注意:若输入阻塞,当前线程将被挂起,如果InputStream对象调用这个方法的话,它只会返回0,这个方法必须由继承InputStream类的子类对象调用才有用。注意:虽然很多InputStream的实现类可以正确的返回输入流的总字节数,但是并不是全都都可以。所以使用这个方法的返回值去分配字节大小来容纳输入流的所有数据一定不是一个正确的方法。
public long skip(long n) 忽略输入流中的n个字节,返回值是实际忽略的字节数, 如果为负数,表示没有跳过任何字节数据。
public int close( ) 关闭输入流,释放分配给输入流的系统资源。

InputStream子类:

InputStream的作用是用来表示那些那些从不同数据源产生输入的类。这些数据源包括:
  • 字节数组
  • String对象
  • 文件
  • "管道",工作方式与实际管道相似,从一端进入,从一端输出
  • 一个由其他种类的流组成的序列,以便我们可以将它们收集合并到一个流内
每一种数据源都有相应的 InputStream子类。另外,FilterInputStream也属于一种InputStream,为"装饰器"类提供基类,其中 "装饰器"类可以把属性或有用的接口与输入流连接在一起。


功能
ByteArrayInputStream 允许将内存中缓冲区当做InputStream使用
StringBufferInputStream 将String转换成InputStream
FileInputStream 用于从文件中读取信息
PipedInputStream 产生用于写入相关PipedOutputStream的数据。实现“管道化”概念。
SequenceInputStream 将两个或者多个InputStream对象转换成单一InputStream
FilterInputStream 抽象类,作为“装饰器”的接口。其中,“装饰器”为其他的InputStream类提供有用的功能。



4.2 OutputSream抽象类

OutputStream提供了3个write方法来做数据的输出,这个是和InputStream是相对应的。

常用方法 描述
public abstract void write(int b) 将指定字节写入到输出流中。一般是将参数b的低八位(一个字节)写入到输出流中。b的高八位被忽略掉。
public void write(byte[] b) 从字节数组b中向输出流中写入b.length个字节数据。
public void write(byte[] b,int off,int len) 从字节数组b偏移位置为off的开始位置向输出流写入len个字节数据。b[off]是第一个被写入的字节,b[off+len-1]是最后一个被写入的字节。如果b为null,会抛出NullPointer异常;如果off或者len是负数,或者off+len比字节数组b的长度大,则会抛出IndexOutOfBoundsException异常。
public void flush() 清空输出流,并强制将所有缓冲的输出字节被写出。
public void close() 关闭输出流,释放分配给输出流的系统资源。


OutputStream的子类:


该类别的类决定了输出所要去往的目标:字节数组(但不是String,不过你当然可以使用字节数组自己来创建),文件或管道。

功能
ByteArrayOutputStream 在内存中创建缓冲区,所有送往“流”的数据都要放置在此缓冲区。
FileOutputStream 用于将信息写至文件。
PipedOutputStream 任何写入其中的信息都会自动作为PipedInputStream的输出。实现“管道化”概念。
FilterOutputStream 抽象类,作为“装饰器”的接口。其中,“装饰器”为其他的OutputStream类提供有用的功能。

5. 字符流 Reader和Writer

当我们初次看到Reader和Writer类时,可能会以为这是两个用来代替InputStream和OutputStream的类,但实际上不是。尽管一些原始的“流”类库不再使用(如果使用它们,则会收到编译器的警告信息),但是InputStream和OutputStream在以面向字节流形式的IO时仍然可以提供有价值的功能。 Reader和Writer则提供了兼容Unicode与面向字符的I/O功能。有时候我们还会把来自"字节"层次结构中的类和来自"字符"层次结构中类 结合使用。为了实现这个目标,我们要用到"适配器"(adapter)类: InputStreamReader可以把InputStream转换为Reader,而OutputStream可以把OutputStream转换为Writer

设计 Reader和Writer继承层次结构是为了国际化。老的IO流继承层次结构只能支持8位字节流,并且不能很好的处理16位的Unicode字符。设计它的目的就是为了在所有的IO操作中都支持Unicode。

Reader的子类:



Writer的子类:
QQ截图20151229213844.png

6. FileInputStream和FileOutputStream

6.1 FileInputStream

FileInputStream 从文件系统中的某个文件中获得输入字节。



(1)构造方法

构造方法 描述
FileInputStream(String name) 使用由name字符串指定路径名文件创建FileInputStream对象
FileInputStream(File file) 使用由file对象指定路径名的文件创建FileInputStream对象

   
   
// FileInputStream(String name)
String path = "D:\\Recommended system.txt";
FileInputStream stream = new FileInputStream(path);
// FileInputStream(File file)
File file = new File(path);
FileInputStream stream2 = new FileInputStream(file);

(2)说明
  • 用于读取诸如图像数据之类的原始字节流。(要读取字符流,请考虑使用 FileReader)
  • 包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。
  • 类本身只是简单地重写那些将所有请求传递给所包含输入流的 InputStream 的所有方法。
  • 其子类可进一步重写这些方法中的一些方法,并且还可以提供一些额外的方法和字段。

(3)实例
   
   
package com.qunar.io;
 
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
 
public class IOUtil {
 
public static void main(String[] args) {
try {
String path = "D:\\demo.txt";
FileInputStream stream = new FileInputStream(path);
int num = 100;
byte[] buff = new byte[num];
while((stream.read(buff,0,num)) != -1){
System.out.println("NewLine->"+new String(buff));
}//while
stream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:

NewLine->My father was a self-taught mandolin player. He was one of the best string instrument players in our
NewLine-> town. He could not read music, but if he heard a tune a few times, he could play it. When he was yo
NewLine->unger, he was a member of a small country music band. They would play at local dances and on a
NewLine->ccasions would play for the local radio station. He often told us how he had auditioned and earned a
NewLine-> position in a band that featured Patsy Cline as their lead singer. He told the family that after he
NewLine-> was hired he never went back. Dad was a very religious man. He stated that there was a lot of drink
NewLine->ing and cursing the day of his audition and he did not want to be around that type of environment.nk


6.2 FileOutputStream

QQ截图20151229221635.png
(1)构造函数

构造函数 描述
FileOutputStream(String name) 使用由name字符串指定路径名的文件创建一个新的文件输出流。
FileOutputStream(String name,boolean append) 使用由name字符串指定路径名的文件创建一个新的文件输出流。如果append参数为true,那么数据将被添加到文件末尾,而具有相同名字的已有文件不会被删除(末尾添加数据);否则这个方法删除所有具有相同名字的已有文件。
FileOutputStream(File file) 使用由file对象指定路径名的文件创建一个新的文件输出流。
FileOutputStream(File file,boolean append) 使用由file对象指定路径名的文件创建一个新的文件输出流。如果append参数为true,那么数据将被添加到文件末尾,而具有相同名字的已有文件不会被删除(末尾添加数据);否则这个方法删除所有具有相同名字的已有文件。

(2)案例

   
   
package com.qunar.io;
 
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class IOUtil {
 
public static void main(String[] args) {
try {
String path = "D:\\from.txt";
String path2 = "D:\\to.txt";
FileInputStream inputStream = new FileInputStream(path);
FileOutputStream outputStream = new FileOutputStream(path2);
int num = 100;
byte[] buff = new byte[num];
// 由文件写至内存
while((inputStream.read(buff,0,num)) != -1){
// 由内存写至文件中
outputStream.write(buff);
}//while
inputStream.close();
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

7. DataInputStream和DataOutputStream

DataInputStream和DataOutputStream是对流的扩展,让我们操作Java基本数据类型更加简单。
数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本Java数据类型。

   
   
package com.qunar.io;
 
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class IOUtil {
 
public static void main(String[] args) {
try {
String path = "D:\\to.txt";
// 向文件写入操作
FileOutputStream outputStream = new FileOutputStream(path);
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
// 向文件中写入一个Int值
dataOutputStream.writeInt(10);
// 向文件中写入一个Double值
dataOutputStream.writeDouble(0.98);
// 向文件中写入一个Long值
dataOutputStream.writeLong(12l);
// 向文件中写入一个UTF-8编码值
dataOutputStream.writeUTF("我来自西安电子科技大学");
//从文件读取操作
FileInputStream inputStream = new FileInputStream(path);
DataInputStream dataInputStream = new DataInputStream(inputStream);
// 从文件中读取一个Int值
System.out.println("从文件中读取一个Int值:" + dataInputStream.readInt());
// 从文件中读取一个Double值
System.out.println("从文件中读取一个Double值:" + dataInputStream.readDouble());
// 从文件中读取一个Long值
System.out.println("从文件中读取一个Long值:" + dataInputStream.readLong());
// 从文件中读取一个UTF-8编码值
System.out.println("从文件中读取一个UTF-8编码值:" + dataInputStream.readUTF());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

运行结果:

   从文件中读取一个Int值:10
   从文件中读取一个Double值:0.98
   从文件中读取一个Long值:12
   从文件中读取一个UTF-8编码值:我来自西安电子科技大学  





本人菜鸟,大牛勿喷,有问题,欢迎留言。。。。





目录
相关文章
|
2月前
|
监控 Java API
如何使用Java语言快速开发一套智慧工地系统
使用Java开发智慧工地系统,采用Spring Cloud微服务架构和前后端分离设计,结合MySQL、MongoDB数据库及RESTful API,集成人脸识别、视频监控、设备与环境监测等功能模块,运用Spark/Flink处理大数据,ECharts/AntV G2实现数据可视化,确保系统安全与性能,采用敏捷开发模式,提供详尽文档与用户培训,支持云部署与容器化管理,快速构建高效、灵活的智慧工地解决方案。
|
12天前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
1月前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
59 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
22天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
107 13
|
27天前
|
算法 Java API
如何使用Java开发获得淘宝商品描述API接口?
本文详细介绍如何使用Java开发调用淘宝商品描述API接口,涵盖从注册淘宝开放平台账号、阅读平台规则、创建应用并申请接口权限,到安装开发工具、配置开发环境、获取访问令牌,以及具体的Java代码实现和注意事项。通过遵循这些步骤,开发者可以高效地获取商品详情、描述及图片等信息,为项目和业务增添价值。
58 10
|
21天前
|
前端开发 Java 测试技术
java日常开发中如何写出优雅的好维护的代码
代码可读性太差,实际是给团队后续开发中埋坑,优化在平时,没有那个团队会说我专门给你一个月来优化之前的代码,所以在日常开发中就要多注意可读性问题,不要写出几天之后自己都看不懂的代码。
57 2
|
30天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
2月前
|
开发框架 Java 关系型数据库
Java哪个框架适合开发API接口?
在快速发展的软件开发领域,API接口连接了不同的系统和服务。Java作为成熟的编程语言,其生态系统中出现了许多API开发框架。Magic-API因其独特优势和强大功能,成为Java开发者优选的API开发框架。本文将从核心优势、实际应用价值及未来展望等方面,深入探讨Magic-API为何值得选择。
69 2
|
2月前
|
监控 前端开发 Java
【技术开发】接口管理平台要用什么技术栈?推荐:Java+Vue3+Docker+MySQL
该文档介绍了基于Java后端和Vue3前端构建的管理系统的技术栈及功能模块,涵盖管理后台的访问、登录、首页概览、API接口管理、接口权限设置、接口监控、计费管理、账号管理、应用管理、数据库配置、站点配置及管理员个人设置等内容,并提供了访问地址及操作指南。
|
2月前
|
IDE Java 编译器
开发 Java 程序一定要安装 JDK 吗
开发Java程序通常需要安装JDK(Java Development Kit),因为它包含了编译、运行和调试Java程序所需的各种工具和环境。不过,某些集成开发环境(IDE)可能内置了JDK,或可使用在线Java编辑器,无需单独安装。
85 1