Java BIO学习总结

来源:互联网 发布:积分或换软件 编辑:程序博客网 时间:2024/06/06 17:03

1、流的概念和作用
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

注意:流只能顺序访问,不能像数组那样随机存取

2、流的分类
根据处理数据类型的不同分为:字符流和字节流
根据数据流向不同分为:输入流和输出流

3、字符流和字节流
字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表
字节流和字符流的区别:
读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。

4、输入流和输出流

输入流可以理解为向内存输入,输出流可以理解为从内存输出
InputStream或者Reader是从数据源读取数据(到内存中),OutputStream或者Writer是将数据(从内存中)写入到目标媒介

典型的数据源或目标媒介有:文件、管道、网络连接、内存缓存、控制台…

注意:Java IO流通常是基于字节或者基于字符的。字节流通常以“stream”命名,比如InputStream和OutputStream。除了DataInputStream 和DataOutputStream 还能够读写int, long, float和double类型的值以外,其他流在一个操作时间内只能读取或者写入一个原始字节

5、组合流

一次读取一个字节是很慢的,借助缓冲可以从磁盘中一次读取一大块数据,然后从读到的数据块中获取字节。为了实现缓冲,可以把InputStream包装到BufferedInputStream中。例如
InputStream input = new BufferedInputStream(new FileInputStream(“xxx”));

6、字符流与字节流之间的转换

例如 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String strLine = bufferedReader.readLine();

借助InputStreamReader可以将字节流转换为字符流

7、常用的几个类说明

// 区分是字符流还是字节流        // 以InputStream或OutputStream结尾是字节流,以Reader或Writer结尾是字符流        // 区分是输入还是输出        // 以Input或Read开头是输入,以Output或Writer结尾时输出        // byte stream        //input stream        String testStr = "heh";        StringBufferInputStream strBufferInputStream = new StringBufferInputStream(testStr); //从String中读取数据到Stream中        strBufferInputStream.read(b); // 从Stream中逐个字节读取        File testFile = new File("filePath");        FileInputStream fileInputStream = new FileInputStream(testFile); //从文件中读取数据到Stream中        byte[] storeByte = new byte[10];        fileInputStream.read(storeByte);    // 从Stream中逐个字节读取  // 文件结尾返回 -1        byte[] testByte = new byte[10];        ByteArrayInputStream byteArrInputStream = new ByteArrayInputStream(testByte); // 从ByteArray中读取数据到Stream中        byteArrInputStream.read(testByte); // 从Stream中逐个字节读取        // output stream        File testFile2 = new File("filePath");  // 写入到哪个文件中去        FileOutputStream fileOutputStream = new FileOutputStream(testFile2);        byte[] srcByte = new byte[10];        fileOutputStream.write(srcByte); // 将byteArray写入到指定文件中        ByteArrayOutputStream byteArrOutputStream = new ByteArrayOutputStream();        byte[] srcByte2 = new byte[10];        byteArrOutputStream.write(srcByte2); // 将byteArray写入到Stream中        // character stream        String encoding = "utf-8";        File testFile3 = new File("filePath");        FileInputStream fileInputStream = new FileInputStream(testFile3);        InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,encoding);        char[] characters = new char[1024];        inputStreamReader.read(characters);  // 逐个字符读取,从字节流中读取并根据编码转换成字符,存入字符数组中        BufferedReader bufferReader = new BufferedReader(inputStreamReader);        bufferReader.readLine(); // 按行读取字符  // 文件结尾返回null

5、读取实例

/**     * BIO模式     * 从输入流中读取指定长度的数据到字节数组中     * 如何确定字节数组长度:file.length()返回字节数组长度     * 如何保证文件内容全部读入:字节数组长度与文件内容长度相等     * @param fileName     * @return     * @throws IOException     */    public static byte[] readByBytes(String fileName) throws IOException{        File file = new File(fileName);        InputStream fileInputStream = new FileInputStream(file);        long length = file.length(); // return length in bytes        System.out.println("file length:" + length);        byte[] fileBytes = new byte[(int)length];        int result = fileInputStream.read(fileBytes);        fileInputStream.close(); // must close        if(result != length){            throw new IOException("can't read all," + result + "!=" + length);        }        System.out.println("read length: " + result);        return fileBytes;    }    /**     * BIO模式     * 逐个字节读取     * 如何确定字节数组长度:file.length()返回字节数     * 如何保证文件内容全部被读取:比较文件长度与读取字节数组长度是否相等     * @param fileName     * @return     * @throws IOException     */    public static byte[] readByOneByte(String fileName) throws IOException{        File file = new File(fileName);        FileInputStream fileInputStream = new FileInputStream(file);        long length = file.length(); // return length in bytes        System.out.println("file length:" + length);        byte[] fileBytes = new byte[(int)length];        int resultByte = fileInputStream.read();        int i = 0; // array index        while(resultByte != -1){            byte tempByte = (byte)resultByte;            fileBytes[i] = tempByte;            i++;            resultByte = fileInputStream.read();        }        fileInputStream.close(); // must close        if(fileBytes.length != length){            throw new IOException("can't read all," + fileBytes.length + "!=" + length);        }        System.out.println("read length: " + fileBytes.length);        return fileBytes;    }    /**     * BIO模式     * FileReader逐个字符读取文件,FileReader extends InputStreamReader     * 读取文件中内容到字符数组中     * 如何确定字符数组长度:     * FileReader不能自定义编码读取     * 此方法也可以用于读取二进制文件,只不过读取出来有很多乱码     * @param fileName     * @return     * @throws IOException     */    public static char[] readByOneCharWithDefaultEncoding(String fileName) throws IOException{        File file = new File(fileName);        FileReader fileReader = new FileReader(file); // 不能自定义编码,内部默认采用系统的编码        System.out.println("当前采用编码: " + fileReader.getEncoding());         char[] charcters = new char[1024];        int result = fileReader.read();  // 逐个字符读取,不能按行读取        int i = 0;        while(result != -1 && i < 1024){            char temp = (char)result;            charcters[i] = temp;            i++;            result = fileReader.read();        }        fileReader.close();        return charcters;    }    /**     * BIO模式     * 逐个字符读取文件     * 读取文件中内容到字符数组中     * 如何确定字符数组长度:     * 此方法也可以用于读取二进制文件,只不过读取出来有很多乱码     * @param fileName     * @return     * @throws IOException     */    public static char[] readByOneCharWithCustomEncoding(String fileName,String encoding) throws IOException{        File file = new File(fileName);        InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(file),encoding);        System.out.println("当前采用编码: " + inputStreamReader.getEncoding());        char[] charcters = new char[1024];        int result = inputStreamReader.read();  // 逐个字符读取,不能按行读取        int i = 0;        while(result != -1 && i < 1024){            char temp = (char)result;            charcters[i] = temp;            i++;            result = inputStreamReader.read();        }        inputStreamReader.close();        return charcters;    }    /**     * BIO模式     * 使用InputStreamReader作为字节流与字符流之间的桥梁     * 使用BufferedReader提升读取效率     * @param fileName     * @throws IOException     */    public static void readByLine(String fileName) throws IOException{        String encoding = "utf-8"; // 既然是读取字符,肯定会涉及到编码问题        File file = new File(fileName);        if(file.isFile() && file.exists()){            InputStream inputStream = new FileInputStream(file);            // inputStreamReader是连接字节流和字符流的桥梁            // 读取指定数量的字节,并按照传入的编码转换成字符            InputStreamReader inputStreamReader = new InputStreamReader(inputStream,encoding);            // 使用BufferedReader的好处是可以一次读取多个字符(而不是一个字符)            BufferedReader bufferReader = new BufferedReader(inputStreamReader);            String readLine = bufferReader.readLine();            while( readLine != null) {                System.out.println(readLine);                readLine = bufferReader.readLine();            }            bufferReader.close();        }    }