java的io(1)---字节流总结

时间:2022-08-10 17:09:24

1、 io初识

1.1、java的io可以说是java最关键的基础部分,因为基本上所有的开发都会用到io,都会有输入输出,都会涉及文件的操作,关于File的使用请看http://blog.csdn.net/jin970505/article/details/78446387

1.2、java的流可以这样分类:
<1>按照处理的数据类型可以分为:字节流和字符流。
<2>按照流的流向可分为输入流和输出流。
<3>按照流的功能可分为节点流和过滤流。
这一篇先来总结字节流。

1.3、java流的框架图:
java的io(1)---字节流总结

2、字节流初识

2.1、在java中,我们一般用字节流来处理字节文件(像图片、视频等),用字符流来处理字符文件,但是由于转换流的存在,我们又可以将两者进行转换,对数据的处理更加灵活。
2.2在字节流中,InputStream和OutputStream是输入输出流的”帮主”,也就是各种字节流的基类,需要注意的是,这两名”帮主”是抽象类,并不能实例化对象,只有其子类才可以实例化。我们下面通过代码和具体的例子来学习。

3、java.io.InputStream

常用方法:

1.void close() 关闭此输入流并释放所有与之有关的资源
2.int   read() 从输入流中读取数据的下一个字节
3.int read(byte[] b) 从输入流中读取一定数量的字节,将其存储在缓冲区字节数组b中。 
4.int read(byte[] buf,int start,int size) 读取数据到字节数组buf从buf的start位置开始存放size长度的数据
****read()方法在返回值为-1时表示输入流到达了终点****

下面来介绍InputStream的子类的用法

4、FileInputStream

基于文件的读取文件的输入流:
1、关联文件建立输入流
2、进行读取操作
3、关闭流

构造方法:

<1>FileInputStream(File file) 根据指定的File对象来建立输入流
<2>FileInputStraem(String name) 根据文件的路径(name)来建立输入流

使用字节流的具体代码,几种建立方式,注意:字节输入流是一个字节一个字节的读取,中文占两个字节,所以在读取的时候,要转换为字符流。

<1>read()方法来读取

public class IoUtil {
  public static void printHex(String FileName) throws IOException{
        //FileName是一个文件路径
        FileInputStream in = new FileInputStream(FileName);

        int b ;
        //while循环外要注意变量的初始化,如果将b=in.read()放在外面,则会形成死循环
        while((b=in.read())!=-1){
        System.out.println(Integer.toHexString(b) + " ");
        }
       in.close();
  }
}

<2>read(byte[] arr)方法:

public class Demo {

    public static void readFile() throws IOException{
        FileInputStream fis = new FileInputStream("F:\\Java.txt");
        //返回文件的总大小,单位是字节
           int num = fis.available();    
           byte[] arr = new byte[num];
        /* * 当数组长度和文件总大小相同时 * 读取一次即可 * 不再需要循环读取 * 但文件太大时不适合用 * 以防内存溢出 */
          int len = fis.read(arr);
          System.out.print(new String(arr,0,len));
    }
}
public static void main(String [] args){
        readFile();
}

<3>read(byte[] buf,int start,int size)方法:

 public static void printHexByByteArray(String fileName)throws IOException{
        FileInputStream in = new FileInputStream(fileName);
        byte[] buf = new byte[20 * 1024];
    //从in中批量读取字节,放入到buf这个字节数组中,从第0个位置开始放,最多放buf.length个,返回的是读到的字节的个数
        int bytes = in.read(buf,0,buf.length);//一次性读完,说明字节数组足够大
    //若一次读不完,可以用while循环,第一次读,若读完,则执行函数,第二次读就跳出循环了,若没有读完,则会继续读buf.length个字节在执行函数,直到读完跳出循环。

       while(( int bytes = in.read(buf,0,buf.length))!=-1){

            int j =0;
            for(int i = 0;i < bytes;i++){
                if(buf[i] <= 0xf){
                //如果是一个字节,就补一个0;
                System.out.print("0");
            }
            System.out.print(Integer.toHexString(buf[i]) + " ");
            if(j++%10==0){
                System.out.println();
            }
    }
}

5、java.io.OutputStream

所有字节输出流的父类,用于将一些字节输出到某个接收器

5.1常用方法:(其中子类必须重写write(int b)才可使用)

void close()  关闭此输出流并释放与输出流有关的系统资源
void flush()  刷新输出流并强制写出缓冲区的所有内容
abstract void write(int b)  将指定的字节写入此输出流
void write(byte []b)  将b.length个字节从指定的b数组中写入到输出流中
void write(byte[]b, int off, int len)  将指定b数组中从偏移量off开始的len个字节写入输出流

6、FileOutputStream

FileOutputStream是将数据写入文件的字节输出流,若要写入字符,考虑FileWrite类。

构造方法概要:

FileOutputStream(File file)  创建一个指向File对象的写入数据的输出流(文件内容会清空,重新写入新的,也就是覆盖原有的内容)
FileOutputStream(File file, boolean flag)  创建一个指向File对象的写入数据的输出流,flag为true时,表示在原有的内容后面追加内容,不会清空
FileOutputStream(String na,e)  创建一个指向name路径文件写入数据的输出流(文件内容会清空,重新写入新的,也就是覆盖原有的内容)
FileOutputStream(String name, boolean flag)  创建一个指向name路径文件的写入数据的输出流,flag为true时,表示在原有的内容后面追加内容,不会清空

一个输出流写的实例:

import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutDemo1 {

    public static void main(String[] args)throws IOException {
        // TODO Auto-generated method stub
        //如果该文件不存在,则直接创建;如果存在,删除后创建
        FileOutputStream out = new FileOutputStream("demo/out.dat",true);
        out.write('A');//写出了'A'的低八位
        out.write('B');//写出了'B'的低八位
        int a = 10;//write()方法只能写低八位,那么写一个int,需要写4次,每次8位。
/*a>>>24的意义: a是一个整型,四个字节,32位,.write()方法一次只能写一个字节,8位,所以如果要写一个整型a,就要写4次,a>>>24位,写32位中的最后8位,以此类推。*/
        out.write(a >>> 24);
        out.write(a >>> 16);
        out.write(a >>> 8);
        out.write(a);
        byte[] gbk = "中国".getBytes("gbk");
//getBytes()函数,将一个字符串转换为一个字节数组
        out.write(gbk);
        out.close();

        IOUtil.printHex("demo/out.dat");

    }

}

通过字节流来拷贝文件:

public static void copyFile(File srcFile,File destFile)throws IOException{
        if(!srcFile.exists()){
            throw new IllegalArgumentException("文件:" + srcFile + "不存在");
        }
        if(!srcFile.isFile()){
            throw new IllegalArgumentException(srcFile + "不是文件");
        }
        FileInputStream in = new FileInputStream(srcFile);
        FileOutputStream out = new FileOutputStream(destFile);//若destFile不存在,则先创建它
        byte[] buf = new byte[8 * 1024];
        int b ;
        while((b = in.read(buf,0,buf.length))!=-1){
            out.write(buf,0,b);
/*write的三种方式: <1>void write(byte[] b)例如: while(c = in.read(b)!=-1){ out.write(b); } 将 b.length 个字节从指定字节数组写入此文件输出流中。 <2>void write(byte[] b, int off, int len) 将指定字节数组中从偏移量 off 开始的 len 个字节写入此文件输出流。 <3>void write(int b) 例如: while(c = in.read()!=-1){ out.write(c); } 将指定字节写入此文件输出流。*/
            out.flush(); // 最好加上
        }
        in.close();
        out.close();
    }

7、BufferedInputStream和BufferedOutputStream

BufferedInputStream和BufferedOutputStream这两个流类为IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能。
FileOutputStream的write()方法相当于一滴一滴地把水“转移”过去;
DataOutputStream的writeXxx()方法相当于一瓢一瓢把水“转移”过去;
BufferedOutputStream的write()方法更方便一些,相当于一瓢一瓢先放入 桶中,在从桶中倒入到另外一个罐中。
需要说明的是:创建BufferedOutStream和BufferedInputStream时,必须在InputStream和OutputStream的前提下建立,例如:
FileInputStream fis = new FileInputStream();
BufferedInputStream bis = new BufferedInputStream(fis);
三种拷贝文件的方法:
<1>逐个逐个字节拷贝文件

public class IoUtil {
    public static void copyFileByByte(File srcFile, File destFile) throws IOException {

        if (!srcFile.exists()) {
            throw new IllegalArgumentException("文件:" + srcFile + "不存在");

        }
        if (!srcFile.isFile()) {
            throw new IllegalArgumentException(srcFile + "不是文件");
        }

        FileInputStream in = new FileInputStream(srcFile);
        FileOutputStream out = new FileOutputStream(destFile);
        int c;
        while ((c = in.read()) != -1) {
            out.write(c);
            // out.flush();
        }
        in.close();
        out.close();

    }

}

<2>利用字节缓冲流来拷贝文件

public class IoUtil {
    public static void copyFileByBuffer(File srcFile, File destFile) throws IOException {

        if (!srcFile.exists()) {
            throw new IllegalArgumentException("文件:" + srcFile + "不存在");

        }
        if (!srcFile.isFile()) {
            throw new IllegalArgumentException(srcFile + "不是文件");
        }

        BufferedInputStream in = new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(destFile));
        int c;
        while ((c = in.read()) != -1) {
            out.write(c);
            out.flush();
        }
        in.close();
        out.close();

    }

}

<3>一次性直接拷贝文件

public class IoUtil {
    public static void copyFileByData(File srcFile, File destFile) throws IOException {

        if (!srcFile.exists()) {
            throw new IllegalArgumentException("文件:" + srcFile + "不存在");

        }
        if (!srcFile.isFile()) {
            throw new IllegalArgumentException(srcFile + "不是文件");
        }

        DataInputStream in = new DataInputStream(new FileInputStream(srcFile));
        DataOutputStream out = new DataOutputStream(new FileOutputStream(destFile));
        int c;
        byte[] arr = new byte[8 * 1024];
        while ((c = in.read(arr, 0, arr.length)) != -1) {
            out.write(arr, 0, c);

        }
        in.close();
        out.close();

    }

}