字节流的介绍与使用
什么是流
在Java中,对数据读写操作, 需要使用流来操作(流是指一连串流动的数据信号,是以先进先出的方式发送和接收数据的通道) , 换句话说,想要对数据进行读和写操作,就得利用流去完成 。
流的分类
⊙ : \odot: ⊙:根据流动方向的不同,流分为输入流和输出流;
⊙ : \odot: ⊙:对于输入和输出流,由于传输格式的不同,又分为字节流和字符流:
A : \mathbb{A}: A:字节流是指8位的通用字节流,以字节为基本单位,在java.io包中,对于字节流进行操作的类大部分继承于InputStream(输入字节流)类和OutputStream(输出字节流)类;
B : \mathbb{B}: B:字符流是指16位的Unicode字符流,以字符(两个字节)为基本单位,非常适合处理字符串和文本,对于字符流进行操作的类大部分继承于Reader(读取流)类和Writer(写入流)类。
IO流体系结构介绍
InputStream和OutputStream
InputStream
字节输入流的父类,抽象类,无法实例化
• available() :获取到当前字节流对象的内容长度
• close() :关闭流资源
• reset() :重置指针的位置,回到最初的位置
• skip(long n) :往前或者往后移动指定长度个位置
• read() :读取指定的文件内容,每次读取一个字节
• read(byte[] b) :读取指定的文件内容,每次读取一个字节数组
• read(byte[] b, int off, int len) :读取指定的文件内容,每次读取一个字节数组,从数组的off的位置开始读取,读取len长度
OutputStream
字节输出流的父类,抽象类,无法实例化
• flush() :刷新缓冲区,让缓冲区里的内容强制输出
• close() :关闭流资源
• write() :读取指定的文件内容,每次读取一个字节
字节流的介绍:输入流(读)
⊙ : \odot: ⊙:FileInputStream类称为文件输入流,继承于InputStream类,是进行文件读操作的最基本类;
⊙ : \odot: ⊙:它的作用是将文件中的数据输入到内存中,我们可以利用它来读文件;
⊙ : \odot: ⊙:由于它属于字节流,因此在读取Unicode字符(如中文)的文件时可能会出现问题。
一个一个字节读
/**
*
* 进行输入流的基本操作:一个字节的操作
*
*/
public class FileInputStreamDemo {
public static void main(String[] args) {
File file = new File("t1.txt");
// 创建一个字节流的对象
InputStream is = null;
try {
is = new FileInputStream(file);
// 通过这字节流来进行读取文件
for (int i = 0; i < file.length(); i++) {
// 读取每一个字节,然后进行强转成char
char ch = (char) is.read();
// 输出
System.out.println(ch);
}
// 当已经把文件完成了读取之后,此时的指针的位置应该在最后,那么我再进行读取的话,会怎么样
System.out.println(is.read());// 已经读完了的话,会返回-1
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
字节数组作为读的缓冲区
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/**
*
* 使用字节数组作为它的缓冲区的读操作
*
*/
public class FileInputStreamDemo1 {
public static void main(String[] args) {
// 创建一个字节流的对象
InputStream is = null;
try {
is = new FileInputStream("t1.txt");
// 构建一个字节数组作为缓冲区,这里默认使用文件大小作为缓冲区大小
// 在真实开发过程中,要根据实际情况来调整缓冲区的大小
// byte [] buff = new byte[512*1024];//512K
byte[] buff = new byte[is.available()];// 512K
// 使用缓冲区来进行读文件
is.read(buff);
// 把缓冲区里面的内容通过String的构造函数的形式来获取出来
String content = new String(buff);
// 内容的输出
System.out.println(content);
// 当已经把文件完成了读取之后,此时的指针的位置应该在最后,那么我再进行读取的话,会怎么样
System.out.println(is.read());// 已经读完了的话,会返回-1
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
小字节数组循环读取
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/**
*
* 使用字节数组作为它的缓冲区的读操作,使用循环来完成所有文件的读取工作
* 字节流+自定义大小的缓冲区这种读取的方式,就是我们工作中使用最为频繁的方式
*
*/
public class FileInputStreamDemo2 {
public static void main(String[] args) {
// 创建一个字节流的对象
InputStream is = null;
try {
is = new FileInputStream("t1.txt");
//定义一个缓冲区,大小是小于文件大小的,所以我们要使用循环来进行读取
byte[] buff = new byte[2];// 512K
//定义一个用来判断下标的int类型的变量index
int index;
//使用while循环来进行判断是否读到了末尾
while((index = is.read(buff))!=-1) {
System.out.println(new String(buff));
}
// 当已经把文件完成了读取之后,此时的指针的位置应该在最后,那么我再进行读取的话,会怎么样
System.out.println(is.read());// 已经读完了的话,会返回-1
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
字节流的介绍:输出流(写)
输出流概述
⊙ : \odot: ⊙:FileOutputStream类称为文件输出流,继承于OutputStream类,是进行文件写操作的最基本类;
⊙ : \odot: ⊙:它的作用是将内存中的数据输出到文件中,我们可以利用它来写文件。
一个一个字节写
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) {
//定义一个字符串,用来进行写入到文件里面去
String source = "Hello World!";
//构建一个文件输出流对象
FileOutputStream fos = null;
try {
File file = new File("t2.txt");
//第二个参数代表你是否进行内容的追加操作,默认是false:不追加
fos = new FileOutputStream(file,true);
//使用循环来进行内容的写入操作
for(int i = 0;i<source.length();i++) {
fos.write(source.charAt(i));
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if(fos!=null)
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
字节数组作为写的缓冲区
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo1 {
public static void main(String[] args) {
//定义一个字符串,用来进行写入到文件里面去
String source = "I love Java!";
//构建一个文件输出流对象
FileOutputStream fos = null;
try {
//第二个参数代表你是否进行内容的追加操作,默认是false:不追加
fos = new FileOutputStream("t2.txt",true);
//构建一个缓冲区
byte [] buff = source.getBytes();
//进行缓冲区的写入
fos.write(buff);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if(fos!=null)
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
过滤流之缓冲流
过滤流的介绍
我们直接使用字节流(也称之为节点流)操作文件的时候,默认操作是一个个的字节,但是很多时候,我们希望读写的不仅仅是一个字节,而是一个字符串、一个double类型的数据等等能够直接用的数据,那么此时,我们就需要借助过滤流来进行操作了,过滤流又称之为处理流、包装流等名词,不管怎么称呼它,它都是在字节流的基础上方便我们操作文件的间接流,它不能直接操作文件。
缓冲流的介绍
在内存与硬盘之间创建一个大小合适的缓冲区,当内存和硬盘进行数据访问时,能够减少访问硬盘的次数,提高效率。缓冲分为字节缓冲流(BufferedInputStream 和 BufferedOutputStream)以及字符缓冲流(BufferedReader 和 BufferedWriter)。
注意:缓冲流其实就是自动帮我们创建了一个缓冲区而已,你想灵活使用的话,仍然可以使用字节流+缓冲区的方式来操作。
一边读一边写
自定义字符数组作缓冲区
private static void testBufferedArea(String path) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(path);
fos = new FileOutputStream("d:api.chm");
byte[] buff = new byte[1024*512];
//代表的是指针的位置
int index;
while((index = fis.read(buff))!=-1) {
//index作为写的长度来避免最后一次写得过多
//fos.write(buff)最后一次写的长度也是1024*512B,但最后面肯很多空字符
fos.write(buff,0,index);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null)
fis.close();
if(fos!=null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用缓冲流(无需自定义缓冲区)
使用缓冲流内部创建字符数组,无需我们手动实现
private static void testBufferedStream(String path) {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(path));
bos = new BufferedOutputStream(new FileOutputStream("d:api1.chm"));
//data代表的就是一个缓冲区的数据
int data;
while((data = bis.read())!=-1) {
bos.write(data);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bis != null)
bis.close();
if(bos!=null)
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
完整代码
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
*
* 该类用来对比字节流+缓冲区以及字节流+过滤流(缓冲流)的写法区别
* 思考:他们的效率区别,注意多调整下缓冲区的大小
*
*/
public class BufferedStreamDemo {
public static void main(String[] args) {
String path = "C:\\Users\\Desktop\\JDK_API_1_6_zh_CN.CHM";
// testBufferedArea(path);
testBufferedStream(path);
}
private static void testBufferedStream(String path) {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(path));
bos = new BufferedOutputStream(new FileOutputStream("d:api1.chm"));
//data代表的就是一个缓冲区的数据
int data;
while((data = bis.read())!=-1) {
bos.write(data);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bis != null)
bis.close();
if(bos!=null)
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void testBufferedArea(String path) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(path);
fos = new FileOutputStream("d:api.chm");
byte[] buff = new byte[1024*512];
//代表的是指针的位置
int index;
while((index = fis.read(buff))!=-1) {
//index作为写的长度来避免最后一次写得过多
//fos.write(buff)最后一次写的长度也是1024*512B,但最后面肯很多空字符
fos.write(buff,0,index);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null)
fis.close();
if(fos!=null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}