Java之字节流、字节缓冲流

来源:互联网 发布:coc野猪升级数据 编辑:程序博客网 时间:2024/05/06 22:58

在上一个刚刚介绍了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();}}