Java:IO流(二)——InputStream/OutputStream具体用法:FileXXXStream、ByteArrayXXXStream
1、说明
InputStream和OutputStream是Java标准库中最基本的IO流,它们都位于java.io包中,该包提供了所有同步IO的功能。
2、模块:java.io.InputStream 、 java.io.OutputStream
3、用法
3.1、read&write
二者都不是接口,而是抽象类,它们分别是所有输入流和输出流的超类。这两个抽象类定义了两个最重要的方法:
- int read():读取输入流的下一个byte,返回该byte表示的int值(0~255)。读到末尾,返回-1表示不能继续读了。
- void write( int b ):写一个byte到输出流。虽然传入的是int,但只会写入1 byte,即该int的最低8位表示字节的部分( b & 0xff )
public abstract int read() throws IOException;
public abstract void write(int b) throws IOException;
3.2、实现类
FileInputStream:从文件流中读取数据
下面的代码演示了如何完整地读取一个FileInputStream的所有字节:
public void readFile throws IOException{
//创建一个FileInputStream对象
InputStream input = new FileInputStream("src/readme.txt");
for(;;){
int n = input.read(); //反复调用read(),直到返回-1
if(n==-1){
break;
}
System.out.println(n);//打印byte值
}
input.close();
}
在计算机中,应用程序如果打开了有一个文件进行读写,完成后要及时关闭,以便OS把资源释放。
FileOutputStream:将若干字节写入文件流
下面代码演示了如何将多个bytes写入文件流:
public void writeFile() throws IOException{
OutputStream output = new FileOutputStream("out/readme.txt");
output.write(72);//H
...
output.write(111);//o
output.close();
}
每次写入1byte太麻烦,更常见的是一次性写入多个bytes。可以通过OutputStream提供的重载方法void write( byte[ ] )来实现:
public void writeFile() throws IOException{
OutputStream output = new FileOutputStream("out/readme.txt");
output.write("Hello".getBytes("UTF-8"));
output.close();
}
3.3、close
在操作完之后,InputStream和OutputStream都需要通过close()来关闭流,之后OS会释放底层资源。
3.3°、flush
只用于OutputStream,目的是将buffer内容真正输出到目的地。
因为写的时候,出于效率考虑,OS不是每次直接把1 byte写入文件或发送到网络,而是先放到内存buffer(本质上是byte [ ]数组),等到buffer写满,再一次性写入文件或网络。
对所有IO设备来说,一次写1B或1000B,花费的时间几乎相同,所以OutputStream有flush()方法,能强制把buffer内容输出。
调用时机
通常情况下,我们不需要调用这个flush(),因为①buffer写满了OutputStream会自动调用它;②调用close()关闭OutputStream之前,也会自动调用flush()方法。
但是某些时机我们需要手动调用flush(),比如在实现一个即时通讯软件时,用户发一句就要flush一句,而不能等待buffer满。
InputStream buffer
InputStream也有buffer。当从FileInputStream读取1 byte时,OS往往会一次性读取多个 bytes到buffer,read时直接返回buffer中的byte,而不是每次都IO 1 byte。
3.4、IOException
读写IO流时,可能发生错误,例如文件不存在、权限异常,它们由JVM封装为IOException抛出。
因此,所有与IO相关的代码都必须处理IOException。
实际使用时,为了避免读取时发生IO错误,IO流无法正确关闭,资源也无法及时释放,所以我们要用try...finally来保证IO流正确关闭:
public void readFile() throws IOException {
InputStream input = null;
try {
input = new FileInputStream("src/readme.txt");
int n;
while ((n = input.read()) != -1) {
System.out.println(n);
}
} finally {
if (input != null) {
input.close();
}
}
}
用try...finally来编写会感觉复杂,更好的写法是利用Java 7引入新的try(resource)语法,只需要编写try语法,就能让编译器自动为我们关闭资源。推荐写法如下:
//InputStream
public void readFile() throws IOException{
try(InputStream input = new FileInputStream("src/readme.txt")){
int n;
while((n=input.read())!=-1)
System.out.println(n);
}//编译器在此自动为我们写入finally并调用close()
} //OutputStream
public void writeFile() throws IOException{
try(OutputStream output = new FileOutputStream("out/readme.txt")){
output.write("Hello".getBytes("UTF-8"));//Hello
}
}
同时操作多个资源时,在try(resource){ ... }中可以同时写出多个资源,用;隔开。例如同时读写两个文件:
//读取input.txt,写入output.txt
try(InputStream input = new FileInputStream("input.txt");
OutputStream output = new FileOutputStream("output.txt")){
input.transferTo(output);
}
不过实际上,编译器并不会特别为InputStream加上自动关闭。只看resource是否实现了java.lang.AutoCloseable接口,如果实现了,就自动加上finally并调用close()方法。InputStream、OutputStream都实现了这个接口,因此都可以用在try( resoucrce )中。
4、缓冲
IO流中,每次用read()、write()读写1 byte未免太麻烦了。IO流各提供了两个重载方法来支持读写多个字节:
- read( byte[ ] b ):从输入流中读取一定数量的bytes,并将之存入缓冲数组b中;
- read( byte[ ] b , int off , int len ):从输出流中off byte处开始读取len bytes到缓冲数组b中;
- write( byte[ ] b ):将b中的所有byte写入输出流中;
- write( byte[ ] b , int off , int len ):从b中的off处开始,写入len bytes到输出流中。
利用read方法一次读取多个bytes时,需要先定义一个byte[ ]作为buffer,read会尽可能多的读取byte到buffer,但不会超过buffer大小。read返回实际读取的byte数,如果返回-1,表示没有更多的数据了。
4.1、read
用buffer一次读取多个bytes的代码如下:
public void readFile() throws IOException{
try(InputStream input = new FileInputStream("src/readme.txt")){
byte[] buffer = new byte[1000];
int n;
while((n=input.read(buffer))!=-1)//读取到buffer
System.out.println("read "+n+" bytes.");
}
}
5、阻塞
之前我们说过java.io是同步io,在进行IO时,会中断程序运行,直到数据IO完毕——此之谓阻塞。
6、其他InputStream实现类
用FileInputStream可以从文件获取输入流,这是InputStream常用的一个实现类。
6.1、ByteArrayInputStream
在内存中模拟一个InputStream:
public class Main {
public static void main(String[] args) throws IOException {
byte [] data ={ 72, 101, 108, 108, 111, 33 };
try(InputStream input = new ByteArrayInputStream(data)){
int n;
while((n=input.read())!=-1)
System.out.println((char)n);
}
}
}
ByteArrayInputStream实际上是把一个byte[ ]数组在内存中变成一个InputStream,虽然应用不多,但测试时可以用来构造一个InputStream。
7、其他OutputStream实现类
7.1、ByteArrayOutputStream
在内存中模拟一个OutputStream:
public class Main {
public static void main(String[] args) throws IOException {
byte[] data;
try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
output.write("Hello".getBytes("UTF-8"));
output.write("world!".getBytes("UTF-8"));
data = output.toByteArray();
}
System.out.println(new String(data, "UTF-8"));
}
}
8、总结
1、InputStream、OutputStream是最基本的IO流,它传输的数据基本单位是byte;
常用的方法有:
- intread():读取输入流的下一个byte,返回该byte表示的int值(0~255)。读到末尾,返回-1表示不能继续读了。
- read( byte[ ] b ):从输入流中读取多个bytes,并将之存入缓冲数组b[ ]中;
- read( byte[ ] b , int off , int len ):从输出流中off byte处开始读取len bytes到缓冲数组b中;
- void write( int b ):写一个byte到输出流。虽然传入的是int,但只会写入1 byte,即该int的最低8位表示字节的部分( b & 0xff )
- write( byte[ ] b ):将b中的所有byte写入输出流中;
- write( byte[ ] b , int off , int len ):从b中的off处开始,写入len bytes到输出流中。
常见实现类有:
- FileXXXStream:文件读写;
- ByteArrayXXXStream:在内存中模拟IO流。
2、用法
//InputStream
public void readFile() throws IOException{
try(InputStream input = new FileInputStream("src/readme.txt")){
byte[] buffer = new byte[1000];
int n;
while((n=input.read(buffer))!=-1)//读取到buffer
System.out.println("read "+n+" bytes.");
}
}
//OutputStream
public void writeFile() throws IOException{
try(OutputStream output = new FileOutputStream("out/readme.txt")){
output.write("Hello".getBytes("UTF-8"));//Hello
}
}
也可以把InputStream和OutputStream资源的创建放在一起:
//读取input.txt,写入output.txt
try(InputStream input = new FileInputStream("input.txt");
OutputStream output = new FileOutputStream("output.txt")){
input.transferTo(output);
}
Java:IO流(二)——InputStream/OutputStream具体用法:FileXXXStream、ByteArrayXXXStream的更多相关文章
- Java IO流(二)
目录 字节缓冲流 概述 BufferedOutputStream类 继承父类的共性成员方法 构造方法 BufferedInputStream类 继承自父类的方法: 构造方法 文件复制练习(增强版 使用 ...
- Java IO流 FileOutputStream、FileInputStream的用法
FileOutputStream.FileInputStream的使用 FileOutputStream是OutputStream的继承类,它的主要功能就是向磁盘上写文件.FileOutputStre ...
- Java IO流 FileOutputStream、FileInputStream的用法
FileOutputStream.FileInputStream的使用 FileOutputStream是OutputStream的继承类,它的主要功能就是向磁盘上写文件.FileOutputStre ...
- Java IO流操作汇总: inputStream 和 outputStream【转】
我们在进行Android java 开发的时候,经常会遇到各种IO流操作.IO流操作一般分为两类:字符流和字节流.以“Reader”结尾都是字符流,操作的都是字符型的数据:以“Stream”结尾的都是 ...
- 《二》Java IO 流的分类介绍
一.根据流向分为输入流和输出流: 注意输入流和输出流是相对于程序而言的. 输出:把程序(内存)中的内容输出到磁盘.光盘等存储设备中 输入:读取外部数据(磁盘.光盘等存储设备的数据)到程序 ...
- Java IO流详解(二)——File类
在上一章博客中简单的介绍了Java IO流的一些特征.也就是对文件的输入输出,既然至始至终都离不开文件,所以Java IO流的使用得从File这个类讲起. File类的描述:File类是文件和目录路径 ...
- Java IO流题库
一. 填空题 Java IO流可以分为 节点流 和处理流两大类,其中前者处于IO操作的第一线,所有操作必须通过他们进行. 输入流的唯一目的是提供通往数据的通道,程序可以通过这个通道读取数 ...
- JAVA.IO流学习笔记
一.java.io 的描述 通过数据流.序列化和文件系统提供系统输入和输出.IO流用来处理设备之间的数据传输 二.流 流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数 ...
- 【Java基础】Java IO流的总结
Java IO流分为输入流和输出流,而输入流和输出流中又分字符流和字节流.顾名思义,输入流则是输入到程序中计算,输出流是把程序的结果输出到文件或者设备.而字符流输入输出以字符为单位,字节流则是以字节为 ...
- Java IO流学习总结八:Commons IO 2.5-IOUtils
Java IO流学习总结八:Commons IO 2.5-IOUtils 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/550519 ...
随机推荐
- 不难懂-----redux
一.flux的缺陷 因为dispatcher和Store可以有多个互相管理起来特别麻烦 二.什么是redux 其实redux就是Flux的一种进阶实现.它是一个应用数据流框架,主要作用应用状态的管理 ...
- linux中sed命令(全面解析)
目录 一:linux中sed命令介绍 1.sed作用 2.sed命令格式 3.参数 4.sed的编辑模式 5.sed参数解析用法 二:sed 参数 -f 案例实战解析 1.前介 2.引入简介 3.方法 ...
- Spring中的单例模式
Spring中的单例模式 单例模式的介绍 1.1 简介 保证整个应用中某个实例有且只有一个 1.2作用 保证一个类仅有一个实例,并且提供一个访问它的全局访问点. 单例模式的优点和缺点 单例模式的优 ...
- 源码安装gitlab
GitLab服务构成 GitLab由以下服务构成: nginx:静态Web服务器 gitlab-shell:用于处理Git命令和修改authorized keys列表 gitlab-workhor ...
- C++ POD 类型
POD 是 C++ 中一个比较重要的概念,POD 是英文 Plain Old Data 的缩写(通俗讲就是类或结构体通过二进制拷贝后还能保持其数据不变),用来描述一个类型(包括 class.union ...
- AI 智能写情诗、藏头诗
一.AI 智能情诗.藏头诗展示 最近使用PyTorch的LSTM训练一个写情诗(七言)的模型,可以随机生成情诗.也可以生成藏头情诗. 在特殊的日子用AI生成一首这样的诗,是不是很酷!下面分享下AI 智 ...
- JSP中的请求转发与重定向
在说请求转发和重定向之前,得了解下JSP九大内置对象中的response和request response:将服务器端数据发送到客户端,可通过在客户端浏览器中显示,用户浏览页面的重定向以及在客户端创建 ...
- C预备知识_001
程序由什么构成? 1.对数据的描述:在程序中要指定用到哪些数据以及这些数据的类型和数据的组织形式,其实这就是数据结构(data structure). 2.对操作的描述:即要求计算机就行操作的步骤,也 ...
- 简单实现UITableView索引功能(中英文首字母索引)(一) ByH罗
UITableView索引功能是常见的,主要是获取中英文的首字母并排序,系统自带获取首字母 //系统获取首字母 - (NSString *) pinyinFirstLetter:(NSString*) ...
- iOS 七大手势之轻拍,长按,旋转手势识别器方法-赵小波
一.监听触摸事件的做法 如果想监听一个view上面的触摸事件,之前的做法通常是:先自定义一个view,然后再实现view的touches方法,在方法内部实现具体处理代码 通过touches方法监听vi ...