1.研究IO流,我们主要研究什么?
  • 怎么new流对象。
  • 调用流对象的哪个方法是读,哪个方法是写。
    因为:java中所有的流都是在:java.io.*;下。
2.什么是IO流?
I : Input
O : Output
通过IO可以完成硬盘文件的读和写。+
3.IO流的分类?
  • 在java中只要“类名”以Stream结尾的都是 字节流。
  • 以“Reader/Writer”结尾的都是 字符流。
3.1.按照流的方向进行分类:以内存为参照
  • 输入流:往内存中去,叫做输入(Input)。或者叫做读(Read)。
  • 输出流:从内存中出来,叫做输出(Output)。或者叫做写(Write)。
3.2.按照读取数据方式不同进行分类:
  • 字节流:按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制位。
    这种流是万能的,什么类型的文件都可以读取。包括:文本文件,图片,声音文件,视频文件等…
假设文件file1.txt,采用字节流的话是这样读的:
  	a中国bc张三fe
  	第一次读:一个字节,正好读到'a'
  	第二次读:一个字节,正好读到'中'字符的一半。
  	第三次读:一个字节,正好读到'中'字符的另外一半。
  • 字符流:一次读取一个字符。
    这种流是为了方便读取普通文本文件而存在的,这种流不能读取:图片、声音、视频等文件。只能读取纯文本文件,连word文件都无法读取。
假设文件file1.txt,采用字符流的话是这样读的:
  	a中国bc张三fe
  	第一次读:'a'字符('a'字符在windows系统中占用1个字节。)
  	第二次读:'中'字符('中'字符在windows系统中占用2个字节。)
4.java IO流这块有四大家族
  • 四大家族的首领都是抽象类。(abstract class)
java.io.InputStream  字节输入流
java.io.OutputStream 字节输出流
java.io.Reader		字符输入流
java.io.Writer		字符输出流
4.1.所有的流都实现了:
  • java.io.Closeable接口,都是可关闭的,都有close()方法。
    流毕竟是一个管道,这个是内存和硬盘之间的通道,用完之后一定要关闭,不然会耗费(占用)很多资源。养成好习惯,用完流一定要关闭。
    4.2.输出流都实现了:
  • java.io.Flushable接口,都是可刷新的,都有flush()方法。
    养成一个好习惯,输出流在最终输出之后,一定要记得flush()刷新一下。这个刷新表示将通道/管道当中剩余未输出的数据强行输出完(清空管道!)刷新的作用就是清空管道。
  • ★★★★★注意:如果没有flush()可能会导致丢失数据。
5.java.io包下需要掌握的流有16个:
  • 文件专属:
    java.io.FileInputStream(掌握)
    java.io.FileOutputStream(掌握)
    java.io.FileReader
    java.io.FileWriter
  • 转换流:(将字节流转换成字符流)
    java.io.InputStreamReader
    java.io.OutputStreamWriter
  • 缓冲流专属:
    java.io.BufferedReader
    java.io.BufferedWriter
    java.io.BufferedInputStream
    java.io.BufferedOutputStream
  • 数据流专属:
    java.io.DataInputStream
    java.io.DataOutputStream
  • 标准输出流:
    java.io.PrintWriter
    java.io.PrintStream(掌握)
  • 对象专属流:
    java.io.ObjectInputStream(掌握)
    java.io.ObjectOutputStream(掌握)
6.字节流,案例分析
  • xx.read();文件的数据都被读取完了,返回-1。
6.1.file = new FileInputStream(“IOtxt.txt”);

目标文件:

java怎么接收流播放语音_java

执行结果:

java怎么接收流播放语音_输出流_02

分析:

1.tempdata=file.read();返回的tempdata是字节数据(eg:a返回97)
2. file.close();在try…catch之后要在finally,关闭流通道。

public class IOTest {
    public static void main(String[] args) throws IOException {
        FileInputStream file =null;//先创建FileInputStream对象
        try {
            /**读取字节流*****/
            // file = new FileInputStream("D:\\JavaSEadvance\\IO\\IOtxt.txt");
            file = new FileInputStream("IOtxt.txt");//相对路径,默认位置是project根目录
            
            int tempdata=0;
            while (tempdata!=-1){
                tempdata=file.read();  /**需要设置,处理异常**/
                System.out.println(tempdata);
            }

        }
        catch (FileNotFoundException e){  /***捕捉异常***/
            e.printStackTrace();
        }finally {
            if (file!=null){    /****如果流没关,则关闭 流******/
                try{
                    file.close();
                }catch (IOException e){
                    e.printStackTrace();
                }

            }
        }
    }
}
6.2.不使用file.available(),向固定长度byte数组中存入内容

目标文件:

java怎么接收流播放语音_输出流_03


执行结果:

java怎么接收流播放语音_数组_04

分析:
  • 1.byte[] bytes2=new byte[5];
    int dataNumber2 = file.read(bytes2);
    每次只读出5个字节,所以abcdefh不能一次输出,一次最多输出5个。
  • 2.System.out.println(new String(bytes2, 0, dataNumber2));
    本次读出多少,就输出多少。因为最后一次读出三个,如果输出整个bytes2,则结果是:fghde,但正确结果是:fgh。所以需要dataNumber2进行数组转换长度限制。
/***向固定长度byte数组中存入内容***/
class IOtest02{
    public static void main(String[] args) {
        FileInputStream file=null;
        try {
            file=new FileInputStream("D:\\JavaSEadvance\\IO\\src\\IOtxt.txt");
            /***不使用file.available(),使用固定数组*****/
            byte[] bytes2=new byte[5];
            while (true) {
                int dataNumber2 = file.read(bytes2);//这个方法返回的是读取字节的数量,而不是字节本身
                //bytes2才是字节本身
                if (dataNumber2==-1)
                    break;
                System.out.println(new String(bytes2, 0, dataNumber2));//只输出本次读取到的“dataNumber2”个字节转成的字符串
            }
        }catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(file!=null) {  //关闭 流
                try {
                    file.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
}
6.3.file.available()的数值就是file文件内所有字节的个数
file.available()长度定义的byte数组中读取内容,数组可一次取出file文件所有字节

目标文件:

java怎么接收流播放语音_输出流_03


执行结果:

java怎么接收流播放语音_数组_06

分析:
  1. byte[] bytes=new byte[file.available()];
    new出的数组长度为file.available(),可以一次放下file文件中的所有字节。
/***向file.available()的长度定义的byte数组中读取内容***/
class IOtest03{
    public static void main(String[] args) {
        FileInputStream file=null;

        try {
            file=new FileInputStream("IOtxt.txt");
            /***使用file.available(),数组可一次取出全部文件字节*****/
            //file.available(),可以得到要读取文件的字节长度,能创建一个数组,直接存整个文件,
            //file.available() 不适用于大文件,因为byte数组不能太大
            byte[] bytes=new byte[file.available()];
            int dataNumber= file.read(bytes);//这个方法返回的dataNumber是读取字节的数量,而不是字节本身
                                                //bytes才是字节本身
            System.out.println("本次读取字节长度:"+dataNumber);

            String str = new String(bytes);//字节数组全部转成字符串
            System.out.println(str);
        }catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(file!=null) {  //关闭 流
                try {
                    file.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
}
6.4.测试skip,跳过几个字节不读

目标文件:

java怎么接收流播放语音_输出流_03

file.skip(5);//跳过5个字节不读

执行结果:

java怎么接收流播放语音_输出流_08

/***测试skip,跳过几个字节不读***/
class IOtest04{
    public static void main(String[] args) {
        FileInputStream file=null;

        try {
            file=new FileInputStream("IOtxt.txt");
            file.skip(5);//跳过5个字节不读


            /***使用file.available(),一个数组取出全部文件字节*****/
            //file.available(),可以得到要读取文件的字节长度,能创建一个数组,直接存整个文件,
            //file.available() 不适用于大文件,因为byte数组不能太大
            byte[] bytes=new byte[file.available()];
            int dataNumber= file.read(bytes);//这个方法返回的是读取字节的数量,而不是字节本身
            System.out.println(dataNumber);

            String str = new String(bytes);//字节数组全部转成字符串
            System.out.println(str);



        }catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(file!=null) {  //关闭 流
                try {
                    file.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }

        }

    }
}
6.5.Fileout测试,从内存向硬盘输出数据
fileOut=new FileOutputStream("myfile",true);
//true:表示会在原文件,末尾,添加字节
//false:表示会清空原文件,重新写入

输出数据:

byte[] bytes={100,101,102,103,104,105,106};

执行1次代码的结果:

java怎么接收流播放语音_java_09


执行2次代码的结果:(在文件末尾,再加入数据)

java怎么接收流播放语音_java_10

分析:

1.fileOut.write(bytes);//执行写入
2.fileOut.flush();//用完输出流,要清空管道,否则可能会丢失数据

/***Fileout测试
 *             //true:表示会在原文件末尾添加字节
 *             //false:表示会清空原文件,重新写入
 *             fileOut=new FileOutputStream("myfile",true);
 * ****/
class IOtest05{
    public static void main(String[] args) {
        FileOutputStream fileOut=null;
        try {
            //"myfile"文件名不存在时,会自动创建
            //这种方式谨慎使用,因为它会将原文件清空,然后重新写入
            //fileOut=new FileOutputStream("myfile");

            //true:表示会在原文件末尾添加字节
            //false:表示会清空原文件,重新写入
            fileOut=new FileOutputStream("myfile",true);

            byte[] bytes={100,101,102,103,104,105,106};
            fileOut.write(bytes);
            fileOut.flush();//用完输出流,要清空管道,否则可能会丢失数据

        }catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileOut!=null){  //关闭 IO流
                try {
                    fileOut.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
6.6.测试文件的copy(可copy各种文件)
分析:

1.创建一个输入流对象

  • fileIn=new FileInputStream(“D:\迅雷下载\星际穿越.mp4”);

2.创建一个输出流对象

  • fileOut= new FileOutputStream(“D:\星际穿越.mp4”);

3.byte[] bytes=new byte[1024*1024];//每次传输1MB

  • 设置每次传输的数据大小
class IOtestFileCopy{
    public static void main(String[] args) {
        FileInputStream fileIn  = null;
        FileOutputStream fileOut= null;

        try {
            //创建一个输入流对象
            fileIn=new FileInputStream("D:\\迅雷下载\\星际穿越.mp4");
            //创建一个输出流对象
            fileOut= new FileOutputStream("D:\\星际穿越.mp4");

            //最核心的一边读,一边写
            byte[] bytes=new byte[1024*1024];//每次传输1MB
            int tempData=0;
            while ((tempData=fileIn.read(bytes))!=-1){
                fileOut.write(bytes,0,tempData);
            }
            //刷新,输出流最后要刷新
            fileOut.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {

            //fileIn、fileOut需要分开try,防止一起try的时候,其中一个出现异常,另一个关闭不了
//            if (fileIn!=null || fileOut!=null){
//                try {
//                    fileIn.close();
//                    fileOut.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }


            //fileIn、fileOut需要分开try,防止一起try的时候,其中一个出现异常,另一个关闭不了
            if (fileIn!=null){
                try {
                    fileIn.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (fileOut!=null){
                try {
                    fileOut.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }


        }
    }
}
6.7.测试普通文本文件的复制(连word也不行)
分析:

1.FileReader()、FileWriter(),只能读取字符型数据

class IOtestTxtCopy{
    public static void main(String[] args) {
        FileReader reader = null;
        FileWriter writer = null;
        try {
            reader = new FileReader("test.txt"); //创建一个读出对象
            writer = new FileWriter("test02");  //创建一个写入对象

            char[] chars = new char[4];  //字符型数据,每次传输4个字符型数据
            int tempData=0;
            while ((tempData=reader.read(chars))!=-1){  //当数据还没读完时
                writer.write(chars,0,tempData); //把每次读出的数据,写入另一个文件
            }
            writer.flush();//输出流刷新,防止丢失数据
        } catch (FileNotFoundException e) {  //捕捉输入流异常
            e.printStackTrace();
        } catch (IOException e) {           //捕捉输出流异常
            e.printStackTrace();
        }
    }
}