14、java——IO流
3、IO流
(1)前提需求: 读写文件内部的内容,上传,下载
(2)流: 管道 数据以先入先出的方式进行流动,数据源--数据-->目的地
(3)io包: 一系列io相关类 File...
(4)流的分类:
①按照流向分:
输入流,输出流
(以大脑为中心,以程序为中心,明确数据源和目的地,能够确定输入还是输出)
②按照操作单元分;
字节流 : 万能流,任意内容都能转为字节,字符流 : 只能传输纯文本的内容
③按照功能分:
节点流 : 真实做读入写出的流,功能流 : 增强节点流的功能,加强性能
分类之间是相辅相成的
(5)字节流:
①字节输入流 InputStream
文件字节输入流 FileInputStream
功能: 节点流 流向分:输入流 操作单元:字节流
功能: 读入read() 关闭close
②字节输出流 OutputStream
public class Class001_IO {
    public static void main(String[] args) throws IOException {
        //FileInputStream(File file) 通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的 File对象 file命名。
        File src = new File("D://test2.txt"); //数据源
        //创建流
        InputStream is = new FileInputStream(src);
        //读入数据 int read() 从此输入流中读取一个字节的数据。  读到文件末尾返回-1
        int num = is.read();
        //处理数据
        System.out.println((char)num);
        System.out.println((char)(is.read()));
        System.out.println((char)(is.read()));
        System.out.println(is.read());
        //关闭流
        is.close();
    }
}
③read() 从此输入流中读取一个字节的数据。 读到文件末尾返回-1
每次读取一个字节,重复通过循环读入,可以简化代码结构
public class Class002_IO {
    public static void main(String[] args) throws IOException {
        //创建流
        //FileInputStream (String name) 通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的路径名 name命名。
        InputStream is = new FileInputStream("D://test2.txt");
        //读入数据
        int num = -1;
        while((num=is.read())!=-1){
            //处理数据
            System.out.println((char)num);
        }
        //关闭流
        is.close();
    }
}
④public byte[] readAllBytes() throws IOException
从输入流中读取所有剩余字节。 此方法将阻塞,直到读取了所有剩余字节并检测到流结束,或者抛出异常。 此方法不会关闭输入流。
当此流到达流的末尾时,此方法的进一步调用将返回空字节数组,请注意,此方法适用于方便将所有字节读入字节数组的简单情况。 它不用于读取包含大量数据的输入流。起始版本: java9
public class Class004_IO {
    public static void main(String[] args) throws IOException {
        //1.构建流
        InputStream is = new FileInputStream("D://test2.txt");
        //2.读入所有数据
        byte[] arr = is.readAllBytes();
        //3.处理数据
        System.out.println(new String(arr));
        //4.关闭
        is.close();
    }
}
(6)字节输出流
①OutputStream 此抽象类是表示输出字节流的所有类的超类。
②FileOutputStream : 文件输出流,将数据写出到指定文件中
③注意:如果目的地文件不存在,系统会自动创建
输出流如果目的地文件存在,内容默认覆盖,设置追加
(7)文件拷贝,数据源--> 读入---> 程序 --> 写出 --> 目的地
步骤:①创建流(输入 输出)②准备小汽车 字节数组③读入-->写出④刷出⑤关闭(后打开的先关闭)
public class Class006_CopyFile {
    public static void main(String[] args){
        //1.创建流(输入 输出)
        //作用域提升,为了能够在finally中使用
        InputStream is = null;
        OutputStream os = null;
        try {
            is = new FileInputStream("D://test.txt");
            os = new FileOutputStream("D://dest.txt");
            //2.准备小汽车 字节数组
            byte[] car = new byte[1024];
            //3.读入-->写出
            int len = -1; //记录每次读入到字节数组中数据的个数
            while((len=is.read(car))!=-1){
                //读入多少字节数据写出多少字节数据
                os.write(car,0,len);
            }
            //4.刷出
            os.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //5.关闭(后打开的先关闭)
            //预防空指针异常出现
            if(os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
(8)字符输入流 : 只能读写纯文本数据
①输入流 : Reader 字符输入流的父类FileReader 文件字符输入流read(),read(char[]),close()
②输出流 : Writer
public class Class001_IO {
    public static void main(String[] args) throws IOException {
        //1.创建流
        //FileReader(String fileName)
        //FileReader(File file)
        Reader rd = new FileReader("D://test.txt");
        //2.读入
        //char ch = (char)(rd.read());
        //小汽车
        char[] car = new char[1024];
        //循环读入
        int len = -1;
        while((len = rd.read(car))!=-1){
            //3.处理数据
            System.out.println(new String(car,0,len));
        }
        //4.关闭
        rd.close();
    }
}
③输出流 : Writer 字符输出流抽象父类,FileWriter 文件字符输出流write(),flush(),close()
public class Class002_IO {
    public static void main(String[] args) throws IOException {
        //1.创建流
       /*
        //FileWriter(File file)
        //FileWriter(String fileName)
        //FileWriter(File file, boolean append)
        //FileWriter(String fileName, boolean append)
*/
        Writer rt = new FileWriter("D://test.txt",true);
        //2.准备数据
        String msg = "今天也要加油鸭!!!";
        //3.写出
        rt.write(msg);
        //4.刷出
        rt.flush();
        //5.关闭
        rt.close();
    }
}
④字符流实现文件拷贝,注意: 只能为纯文本文件
1、拷贝文件夹 :
(1)判断要拷贝的文件是文件还是文件夹
是文件: 调用工具类实现文件拷贝
是文件夹: 创建文件夹,遍历数据源文件夹,获取到所有的子文件然后重复
public static void main(String[] args) {
        copyDir("D://DDD","D://haha");
    }
    //拷贝文件夹
    public static void copyDir(String src,String dest){
        copyDir(src!=null?new File(src):null,dest!=null?new File(dest):null);
    }
    public static void copyDir(File src, File dest){
        if(src==null || dest==null){
            throw new NullPointerException();
        }
        if(!src.exists()){
            System.out.println("数据源不存在!!!");
            return;
        }
        //拷问文件夹|文件
        copyDetail(src,dest);
    }
    //实现拷贝细节
    public static void copyDetail(File src,File dest){
        //拼接完整目的地路径
        dest = new File(dest,src.getName());  //D:\haha\hehe\DDD
        //文件
        if(src.isFile()){
            //如果目的地路径不存在
           if(!dest.getParentFile().exists()){
               dest.getParentFile().mkdirs();
           }
            //文件拷贝
            CopyFileUtils.copyFile(src,dest);
        }else if (src.isDirectory()){
            //文件夹
            //创建不存在的目的地路径
            dest.mkdirs();
            //遍历数据源
            File[] arr = src.listFiles();
            for(File file:arr){   //D:\DDD\a.txt
                copyDetail(file,dest);  ////D:\haha\hehe\DDD
            }
        }
    }
}
(2)按照功能分:
①节点流 : 真实做读入写出②功能流 : 加强性能③功能流都要包裹节点流使用
④缓冲流 : 功能流⑤作用: 提高读写效率
⑥字节节点流:
FileInputStream 文件流 | ByteArrayInputStream 字节数组流
FileOutputStream | ByteArrayOutputStream
⑤字节缓冲流 : 字节流功能流的一种
BufferedInputStream 字节输入缓冲流
BufferedOutputStream 字节输出缓冲流
⑥无新增功能,可以发生多态
⑦字符节点流
FileReader,FileWriter
⑧字符缓冲流
BufferedReader,BufferedWriter
存在新增方法: 不能发生多态
readLine(),newLine()
public class Class001_Buffered {
    public static void main(String[] args) throws IOException {
        //1.创建流
        InputStream is = new BufferedInputStream(new FileInputStream("D://test.txt"));
        OutputStream os = new BufferedOutputStream(new FileOutputStream("D://heihei.txt"));
        //2.拷贝
        byte[] car = new byte[1024];
        int len = -1;
        while((len=is.read(car))!=-1){
            os.write(car,0,len);
        }
        //3.刷出
        os.flush();
        //4.关闭
        os.close();
        is.close();
    }
}
2、基本数据类型流|Data流
(1)功能: 功能流 操作单元: 字节流
(2)作用: 保留数据已经数据类型(基本数据类型+String)
DataInputStream,新增功能: readXxx()
DataOutputStream,新增功能: writeXxx()
(3)注意:①读入与写出的顺序要保持一致②java.io.EOFException : 读入的文件不是源文件
public class Class001_Data {
    public static void main(String[] args) throws IOException {
        readFromFile("D:/d.txt");
    }
    //读入
    public static void readFromFile(String path) throws IOException {
        //1.创建流
        DataInputStream is = new DataInputStream(new BufferedInputStream(new FileInputStream(path)));
        //2.读入
        int i = is.readInt();
        boolean flag = is.readBoolean();
        char ch = is.readChar();
        String s = is.readUTF();
        //3.处理数据
        System.out.println(i);
        System.out.println(flag);
        System.out.println(ch);
        System.out.println(s);
        //4.关闭
        is.close();
    }
    //写出
    public static void writeToFile(String path) throws IOException {
        //1.创建输出流
        DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
        //2.准备数据
        int i = 1;
        boolean flag = false;
        char ch = 'c';
        String str = "哈哈";
        //3.写出
        out.writeInt(i);
        out.writeBoolean(flag);
        out.writeChar(ch);
        out.writeUTF(str);
        //4.刷出
        out.flush();
        //5.关闭
        out.close();
    }
}
3、Object 流| 对象流 | 引用数据类型流
(1)作用: 读写对象数据|引用数据类型的数据(包含基本数据类型)
ObjectInputStream 反序列化输入流,新增功能: readObject()
ObjectOutputStream 序列化输出流,新增功能: writeObject(Object obj)
(2)序列化: 将对象数据转换一个可存储或者可传输的状态过程
(3)特性:
①先序列化后反序列化
②不能所有的类型都能序列化 java.io.Serializable
③不是所有的属性都需要序列化
④静态的内容不会序列化
⑤如果父类实现序列化,子类没有实现,可以序列化所有的成员
⑥如果子类实现序列化,父类实现,只能序列化子类成员
(4)通过序列号控制版本不一致问题:
①实现Serializable接口的类型默认生成序列号,序列号会根据成员的修改做更新 serialVersionUID = -5204947308809070324
②控制版本的统一问题: 控制类型修改之前与之后序列不变
③通过工具生成序列号: a.实现Serializable接口 b.setting设置 c.选中类名->alt+enter->生成序列号
public class Class001_Object {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //writeToFile("D://e.txt");
        readFile("D://e.txt");
    }
    //反序列化
    public static void readFile(String path) throws IOException, ClassNotFoundException {
        //1.输入流
        ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(path)));
        //2.读入
        User obj1 = (User) in.readObject();
        int[] arr = (int[]) in.readObject();
        //3.处理数据
        System.out.println(obj1);
        System.out.println(Arrays.toString(arr));
        //4.关闭
        in.close();
    }
    //序列化输出
    public static void writeToFile(String path) throws IOException {
        //1.输出流
        ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
        //2.数据
        User user = new User("zhangsan",18,"123");
        int[] arr = {1,2,3,4};
        //3.写出
        out.writeObject(user);
        out.writeObject(arr);
        //4.刷出
        out.flush();
        //5.关闭
        out.close();
        //修饰user对象的成员,静态
        user.username = "lisi";
        user.password = "4321";
    }
}
class User implements Serializable{
    private static final long serialVersionUID = -5204947308809070324L;
    public String username;
    //transient 修饰的字段不会序列化
    public transient int age;
    public static String password;
    //成员的修改: 新增的成员
    public int vip;
    public int id;  //用户编号
    public User() {
    }
    public User(String username, int age, String password) {
        this.username = username;
        this.age = age;
        this.password = password;
    }
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", age=" + age +
                ", password='" + password + '\'' +
                '}';
    }
}
(1)CommonsIO 是apache的一个开源的工具包,封装了IO操作的相关类,使用Commons IO可以很方便的读写文件,url源代码等。
(2)使用第三方组件的方式|步骤:
①下载源码资源,找到核心jar包
②项目下新建文件夹lib,放入jar包
③commons-IO 需要加入classpath 的第三方 jar 包内的 class 文件才能在项目中使用,选中jar包右键->add as lib...
public class Class001_CommonsIO {
    public static void main(String[] args) throws IOException {
        //1.创建File对象
        File src = new File("D://a.txt");
        File dest = FileUtils.getFile("D://f.txt");
        //FilenameUtils
        //isExtension(String fileName, String text) // 判断fileName是否是text后缀名
        //FilenameUtils.getBaseName(String filename) // 去除目录和后缀后的文件名       System.out.println(FilenameUtils.getBaseName("D://DDD/haha.txt"));;        System.out.println(FilenameUtils.getName("D://DDD/haha.txt"));;       System.out.println(FilenameUtils.isExtension("D://DDD/haha.txt","txt"));;
        //FileUtils
        //FileUtils.copyFile(File srcFile, File destFile)` // 复制文件
        FileUtils.copyFile(src,dest);
        // **复制文件夹**
        //FileUtils.copyDirectory(File srcDir, File destDir)` // 复制文件夹(文件夹里面的文件内容也会复制)
        FileUtils.copyDirectory(new File("D://DDD"), new File("D://hehe/DDD"));
        //FileUtils.copyDirectory(File srcDir, File destDir, FileFilter filter)` // 复制文件夹,带有文件过滤功能
        FileUtils.copyDirectory(new File("D://DDD"),  new File("D://houhou/DDD"), FileFilterUtils.fileFileFilter());
        //**把字符串写入文件**
        //`FileUtils.writeStringToFile(File file, String data, String encoding)`  // 字符串以指定的编码写到文件
        //`FileUtils.writeStringToFile(File file, String data, String encoding, boolean append)`// 指定知否追加
        FileUtils.writeStringToFile(src,"yyds!!!!","UTF-8",true);
    }
}
                    
                
                
            
        
浙公网安备 33010602011771号