您的位置:首页 > 编程语言 > Java开发

Java之字节流、字节缓冲流

2017-07-01 22:15 267 查看
在上一个刚刚介绍了File类,创建了文件或者文件夹,但是里面的数据是怎么操作它呢,若想操作文件中的数据,需要借助字节流或者字符流。

字节流
字节流是由字节组成的,字符流是由字符组成的.
IO流的分类

- 字节流

    - 字节输入流 InputStream 抽象类

        -  FileInputStream 操作文件的字节输入流

    - 字节输出流 OuputStream抽象类

        -FileOutputStream 操作文件的字节输出流

- 字符流

    - 字符输入流 Reader抽象类

        - InputStreamReader 输入操作的转换流

            - FileReader 用来操作文件的字符输入流(简便的流)

    - 字符输出流 Writer抽象类

        - OutputStreamWriter 输出操作的转换流

            - FileWriter 用来操作文件的字符输出流(简便的流)

字节输出流OutputStream
OuputStream是一个抽象类,表示输出字节流的所有类的超类,操作的数据都是字节,字节流处理单元为一个字节。

使用OuputStream该抽象类的子类如FileOutputStream、ObjectOutputStream.
字节输出流中定义的方法主要为write方法,如:
void write(byte[] b);//将b.length个字节从指定的byte数组写入此输出流。
void write(byte[] b,int off,int len);//将指定的byte数组中从偏移量off开始的冷个字节写入此输出流。
abstract void write(int b);//将指定的字节写入此输出流。
FileOutputStream类
即文件输出流,是用于将数据写入
File
的输出流。

构造方法
FileOutputStream(File file);//创建一个向指定File对象表示的文件中写入数据的文件输出流
FileOutputStream(String name);//创建一个向指定路径名字符串表示的文件中写入数据的文件输出流

实例-写入数据到文件中:
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
//需求:将数据写入到文件中。
//创建存储数据的文件。
File file = new File("c:\\file.txt");
//创建一个用于操作文件的字节输出流对象。一创建就必须明确数据存储目的地。
//输出流目的是文件,会自动创建。如果文件存在,则覆盖。
FileOutputStream fos = new FileOutputStream(file);//使用传入File对象的构造方法
//调用父类中的write方法。
byte[] data = "abcde".getBytes();//使用String类中的getBytes方法将String对象变为Byte数组
fos.write(data);
//关闭流资源。
fos.close();
}
}


IO异常处理
在实际开发中,创建一个文件并向该文件内写入数据,并关掉,可能会发生异常。实例代码
public class FileOutputStreamDemo3 {
public static void main(String[] args) {
File file = new File("c:\\file.txt");
//定义FileOutputStream的引用
FileOutputStream fos = null;
try {
//创建FileOutputStream对象
fos = new FileOutputStream(file);
//写出数据
fos.write("abcde".getBytes());
} catch (IOException e) {
System.out.println(e.toString() + "----");
} finally {
//一定要判断fos是否为null,只有不为null时,才可以关闭资源
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException("");
}
}
}
}
}

字节输入流InputStream

特点是从内存将文件中的数据读出,InputStream可以实现,该类仍为抽象类,是表示字节数入流的所有类的超类,使用它的子类如:FileInputStream,ObjectInputStream。
FileInputStream从文件系统中的某个文件中获得输入字节,

FileInputStream类的构造方法

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

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

FileInputStream主要方法

int read();//从输入流中读取的下一个字节,一次只能读一个字节。
int read(byte[] b);//从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
int read(byte[] b,int off,int len);//将输入流中最多 len 个数据字节读入 byte 数组。1.使用read()方法实例:
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
File file = new File("c:\\file.txt");
//创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
FileInputStream fis = new FileInputStream(file);
//读取数据。使用 read();一次读一个字节。
int ch = 0;
while((ch=fis.read())!=-1){
System.out.println("ch="+(char)ch);
}
// 关闭资源。
fis.close();
}
}
此方法缺点在于读取大文件时,速度太慢。
2. 使用read(byte[ ])方法实例:
public class FileInputStreamDemo2 {
public static void main(String[] args) throws IOException {
/*
* 演示第二个读取方法, read(byte[]);
*/
File file = new File("c:\\file.txt");
// 创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
FileInputStream fis = new FileInputStream(file);
//创建一个字节数组。
byte[] buf = new byte[1024];//长度可以定义成1024的整数倍。
int len = 0;
while((len=fis.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
fis.close();
}
}
读取是通过创建一个字节数组,读取一个字节数组的大小再写入程序中,此方法的优势在于速度快。

3. 使用字节缓冲输入流BufferedInputStream实例:
/*
* 从文件中读取数据
* 1,创建缓冲流对象
* 2,读数据,打印
* 3,关闭
*/
private static void read() throws IOException {
//1,创建缓冲流对象
FileInputStream fileIn = new FileInputStream("abc.txt");
//把基本的流包装成高效的流BufferedInputStream in = new BufferedInputStream(fileIn);
//2,读数据
int ch = -1;
while ( (ch = in.read()) != -1 ) {
//打印
System.out.print((char)ch);
}
//3,关闭
in.close();
}


使用字节流实现复制文件

原理是读取一个已有的数据,并将这些数据写入到另一个文件中。

public class CopyFileTest {
public static void main(String[] args) throws IOException {
//1,明确源和目的。
File srcFile = new File("c:\\YesDir\test.JPG");
File destFile = new File("copyTest.JPG");

//2,明确字节流 输入流和源相关联,输出流和目的关联。
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);

//3, 使用输入流的读取方法读取字节,并将字节写入到目的中。
int ch = 0;
while((ch=fis.read())!=-1){
fos.write(ch);
}
//4,关闭资源。
fos.close();
fis.close();
}
}

上述代码输入流和输出流之间是通过ch这个变量进行数据交换的。

上述复制文件有个问题,每次都从源文件读取一个,然后在写到指定文件,接着再读取一个字符,然后再写一个,一直这样下去。效率极低。

使用缓冲数组方式复制文件
public class CopyFileByBufferTest {
public static void main(String[] args) throws IOException {
File srcFile = new File("c:\\YesDir\test.JPG");
File destFile = new File("copyTest.JPG");
// 明确字节流 输入流和源相关联,输出流和目的关联。
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
//定义一个缓冲区。
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);// 将数组中的指定长度的数据写入到输出流中。
}
// 关闭资源。
fos.close();
fis.close();
}
}


字节缓冲流

在进行过读取文件中数据的操作,读取数据量大的文件时,读取的速度会很慢,很影响我们程序的效率,Java中提高了一套缓冲流,它的存在,可提高IO流的读写速度。
缓冲流,根据流的分类分类字节缓冲流与字符缓冲流。

字节缓冲流:
1. 字节缓冲输出流 BufferedOutputStream
2. 字节缓冲输入流 BufferedInputStream

它们的内部都包含了一个缓冲区,通过缓冲区读写,就可以提高了IO流的读写速度

1. 字节缓冲输出流 BufferedOutputStream

构造方法:

BufferedOutputStream(OutputStream out);//创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
BufferedOutputStream(OutputStream out,int size);//创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。
其参数为:字节输出流的对象
实例:
public class BufferedOutputStreamDemo01 {
public static void main(String[] args) throws IOException {

//写数据到文件的方法
write();
}

/*
* 写数据到文件的方法
* 1,创建流
* 2,写数据
* 3,关闭流
*/
private static void write() throws IOException {
//创建基本的字节输出流
FileOutputStream fileOut = new FileOutputStream("abc.txt");
//使用高效的流,把基本的流进行封装,实现速度的提升
BufferedOutputStream out = new BufferedOutputStream(fileOut);
//2,写数据
out.write("hello".getBytes());
//3,关闭流
out.close();
}
}

2. 字节缓冲输入流 BufferedInputStream
构造方法
public BufferedInputStream(InputStream in);//创建一个
BufferedInputStream
并保存其参数,即输入流
in
,以便将来使用。

public BufferedInputStream(InputStream in,size);//创建具有指定缓冲区大小的
BufferedInputStream
并保存其参数,即输入流
in
,以便将来使用。

其参数为字节输入流的对象。
实例:
/*
* 从文件中读取数据
* 1,创建缓冲流对象
* 2,读数据,打印
* 3,关闭
*/
private static void read() throws IOException {
//1,创建缓冲流对象
FileInputStream fileIn = new FileInputStream("abc.txt");
//把基本的流包装成高效的流BufferedInputStream in = new BufferedInputStream(fileIn);
//2,读数据
int ch = -1;
while ( (ch = in.read()) != -1 ) {
//打印
System.out.print((char)ch);
}
//3,关闭
in.close();
}

使用基本的流与高效的流完成复制文件

我们一直在说,高效的流速度快并高效,怎么体现呢?需要通过一个复制文件耗时的比较过程,来体验一下高效流带来的快感。

/*
* 需求:将d:\\test.avi文件进行复制
* 采用4种方式复制
* 方式1: 采用基本的流,一次一个字节的方式复制 共耗时 224613毫秒
* 方式2: 采用基本的流,一个多个字节的方式赋值 共耗时 327毫秒
* 方式3: 采用高效的流,一次一个字节的方式复制 共耗时 2047毫秒
* 方式4: 采用高效的流,一个多个字节的方式赋值 共耗时 96毫秒
*
* 数据源: d:\\test.avi
* 目的地1: d:\\copy1.avi
* 目的地2: d:\\copy2.avi
* 目的地3: d:\\copy3.avi
* 目的地4: d:\\copy4.avi
*
* 实现的步骤:
* 1,指定数据源
* 2,指定目的地
* 3,读数据
* 4,写数据
* 5,关闭流
*
*/
public class CopyAVI {
public static void main(String[] args) throws IOException {
//开始计时
long start = System.currentTimeMillis();
//方式1: 采用基本的流,一次一个字节的方式复制
//method1("d:\\test.avi", "d:\\copy1.avi");
//方式2: 采用基本的流,一个多个字节的方式赋值
//method2("d:\\test.avi", "d:\\copy2.avi");
//方式3: 采用高效的流,一次一个字节的方式复制
//method3("d:\\test.avi", "d:\\copy3.avi");
//方式4: 采用高效的流,一个多个字节的方式赋值
method4("d:\\test.avi", "d:\\copy4.avi");

//结束计时
long end = System.currentTimeMillis();
//打印耗时多少毫秒
System.out.println("共耗时 " +(end - start)+ "毫秒");
}

//方式4: 采用高效的流,一个多个字节的方式赋值
private static void method4(String src, String dest) throws IOException {
//1,指定数据源BufferedInputStream in = new BufferedInputStream(new FileInputStream(src));
//2,指定目的地
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dest));
//3,读数据
byte[] buffer = new byte[1024];
int len = -1;
while ( (len = in.read(buffer)) != -1) {
//4,写数据
out.write(buffer, 0, len);
}
//5,关闭流
in.close();
out.close();
}

//方式3: 采用高效的流,一次一个字节的方式复制
private static void method3(String src, String dest) throws IOException {
//1,指定数据源BufferedInputStream in = new BufferedInputStream(new FileInputStream(src));
//2,指定目的地
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dest));
//3,读数据
int ch = -1;
while ((ch=in.read()) != -1) {
//4,写数据
out.write(ch);
}
//5,关闭流
in.close();
out.close();
}

//方式2: 采用基本的流,一个多个字节的方式赋值
private static void method2(String src, String dest) throws IOException {
//1,指定数据源
FileInputStream in = new FileInputStream(src);
//2,指定目的地
FileOutputStream out = new FileOutputStream(dest);
//3,读数据
byte[] buffer = new byte[1024];
int len = -1;
while ( (len=in.read(buffer)) != -1) {
//4,写数据
out.write(buffer, 0, len);
}
//5,关闭流
in.close();
out.close();
}

//方式1: 采用基本的流,一次一个字节的方式复制
private static void method1(String src, String dest) throws IOException {
//1,指定数据源
FileInputStream in = new FileInputStream(src);
//2,指定目的地
FileOutputStream out = new FileOutputStream(dest);
//3,读数据
int ch = -1;
while (( ch=in.read()) != -1) {
//4,写数据
out.write(ch);
}
//5,关闭流
in.close();
out.close();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐