JavaIO流 Note [vaynexiao]

关系图

在这里插入图片描述

分类

按用途划分(处理流 包装流):
缓冲流(Buffer)
数据流(DataInputStream)
打印流:PrintWriter 字符输出流,PrintStream 字节输出流
对象流:ObjectOutputStream

按方向:输入流 输出流
按数据单位:字节流byte 字符流char

RandomAccessFile随机读写流

随机读写流,是一个字节流,可以对文件进行任意位置读写

  • 随机:可以定位到文件的任意位置进行读写操作,通过移动指针(Pointer)来实现
  • 读写:使用该流既能读取文件,也能写入文件
		try(
            /*
            *  当文件不存在时:
            *      如果模式为r,会报异常FileNotFoundException
            *      如果模式为rw,会自动创建文件
            *      模式:r只读、rw读写
            */
            RandomAccessFile raf=new RandomAccessFile("c:\\test\\w.txt", "rw"); 
        ){
    
    
            System.out.println(raf.getFilePointer()); // 获取当前指针的位置,从0开始

            raf.write("张三".getBytes()); //对于utf-8,一个汉字占3个字节
            raf.write("hello".getBytes());
            System.out.println(raf.getFilePointer()); // 11

            System.out.println("写入成功");

            raf.seek(8); // 将指针移动到指定的位置
            raf.write("李四".getBytes());
            System.out.println(raf.getFilePointer()); // 14

            raf.seek(6);
            byte[] buffer = new byte[2];
            raf.read(buffer);
            System.out.println(new String(buffer));
            System.out.println(raf.getFilePointer()); // 8

            raf.skipBytes(3); // 将指针向后跳过指定的字节,只能往前,不能倒退 ——>
            buffer = new byte[1024*1024];
            int num = -1;
            while((num = raf.read(buffer)) != -1){
    
    
                System.out.println(new String(buffer,0,num));
            }

            // 修改数据
            raf.seek(8);
            raf.write("赵".getBytes());
            System.out.println("修改成功");
        }catch(IOException e){
    
    
            e.printStackTrace();
        }

ObjectInputStream对象输入输出流

如果希望将Java对象写入到IO流中,或从IO流中读取Java对象,则要使用对象输入输出流,称为对象的序列化和反序列化
 
4.1 序列化和反序列化
序列化:将Java对象写入IO流中,实现将对象保存在磁盘上或在网络中传递对象
反序列化:从IO流中读取Java对象,实现从磁盘上或网络中恢复对象
    要求:
    对象必须实现Serializable接口,才能被序列化,转换为二进制流,通过网络进行传输
    通过 serialVersionUID 判断对象的序列化版本的一致性:
        在反序列时,会将流中的serialVersionUID与本地相应实体对象/类的serialVersionUID进行比较
            如果相同就认为版本一致,则可以进行反序列化
            如果不相同,则会出现序列化版本不一致的异常InvalidClassException
 
4.2 ObjectInputStream
对象输入流:用来读取对象,即反序列化
ObjectInputStream 和 ObjectOutputStream 属于包装流(用于对节点流进行功能扩展 / 包装)
在创建包装流,需要传入要操作的节点流对象
当关闭流时,只需要关闭包装流,被包装的节点流也会被关闭
 
4.3 ObjectOutputStream
对象输出流:用来写入对象,即序列化

User.java

public class User implements Serializable {
    
    
    // static final long serialVersionUID
    // 根据类名、接口名、成员方法和属性等生成的一个64位的哈希值
    // 表示对象类型的的唯一标识
    private static final long serialVersionUID = 705661196096434175L;
    private Integer id; // 都使用包装类型,默认为null
    private String name;
    private transient Integer age;  // transient修饰的属性不会被序列化(static变量也不会被序列化)
    private Address address; // 对象属性也必须实现Serializable接口
    //  ...
}

Address.java

public class Address implements Serializable {
    
    
    private String province;
    private String city;
     //  ...
}

Test.java

public class Test01 {
    
    
    public static void main(String[] args) {
    
    
        test01();
        test02();
    }
    // 序列化,写入对象
    public static void test01() {
    
    
        User u1 = new User(1001, "tom", 18);
        u1.setAddress(new Address("江苏", "南京"));

        User u2 = new User(1002, "jack", 21);
        u1.setAddress(new Address("江苏", "扬州"));

        List<User> users = Arrays.asList(u1, u2);
        ObjectOutputStream oos = null;
        try {
    
    
            // FileOutputStream fos = new FileOutputStream("user.data");
            // oos = new ObjectOutputStream(fos);
            // 输出到user.data文件中,是二进制文件,文本编辑器打开不能正常显示
            oos = new ObjectOutputStream(new FileOutputStream("user.data"));
            
            // 写入对象
            // oos.writeObject(u1);
            // oos.writeObject(u2);
            oos.writeObject(users);
            oos.flush(); // 这里不flush也行,后面有close
            System.out.println("写入对象成功");
        } catch (FileNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if (oos != null) {
    
    
                try {
    
    
                    oos.close(); // 只需要关闭包装流
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }
    // 反序列化,读取对象
    public static void test02() {
    
    
        ObjectInputStream ois = null;
        try {
    
    
            ois = new ObjectInputStream(new FileInputStream("user.data"));
            // 读取顺序和写入顺序一致
            // User u1 = (User) ois.readObject();
            // User u2 = (User) ois.readObject();
            // System.out.println(u1);
            // System.out.println(u2);
            List<User> list = (List<User>) ois.readObject();
            System.out.println(list);
        } catch (FileNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if (ois != null) {
    
    
                try {
    
    
                    ois.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }
}

IO案例

递归获取指定目录下所有文件

public class Test01 {
    
    
    public static void main(String[] args) throws URISyntaxException, IOException {
    
    
        File file = new File("c:/idea_pro");
        display(file);
    }
    public  static  void  display(File  file)  {
    
    
        if  (!file.exists())  {
    
     
            return; 
        }
        if  (file.isDirectory())  {
    
    
            File[]  files  =  file.listFiles();
            for  (File  f  :  files)  {
    
    
                if(f.isFile()){
    
    
                    System.out.println(f.getAbsolutePath());
                }else{
    
    
                    display(f);
                }
            }
        }else{
    
    
            System.out.println(file.getAbsolutePath());
        }
    }
}

递归删除全部空目录

public class Test01 {
    
    
    public static void main(String[] args) throws URISyntaxException, IOException {
    
    
        File file = new File("d:/resource");
        remove(file);
    }
    public static void remove(File file) {
    
    
        // 判断是否为空目录
        if (file.isDirectory() && file.listFiles().length == 0) {
    
    
            file.delete();
            System.out.println("删除空目录:" + file.getAbsolutePath());
            // 删除当前目录后可能导致父目录也为空,所以需要对父目录进行处理
            remove(file.getParentFile());
        } else if (file.isDirectory()) {
    
    
            // 如果当前目录不为空目录,则获取目录下所有文件进行再处理
            File[] files = file.listFiles();
            for (File f : files) {
    
    
                remove(f); // 递归删除
            }
        }
    }
}

文件的加密

实现文件的加密 a.txt ——> a.txt.sec

思路:读取文件中的每个字节,与pwd进行异或的操作

public class Test01 {
    
    
    public static void main(String[] args) {
    
    
        Scanner input = new Scanner(System.in);
        System.out.print("请输入文件路径:");
        String filePath=input.nextLine();
        System.out.print("请输入密码:");
        int pwd = input.nextInt();
        secret(filePath, pwd);
        System.out.println("加密成功");
    }
    public static void secret(String filePath, int pwd){
    
    
        try(
            FileInputStream fis=new FileInputStream(filePath);
            FileOutputStream fos = new FileOutputStream(filePath+".sec");
        ){
    
    
            int data=-1;
            while((data=fis.read())!=-1){
    
    
                fos.write(data ^ pwd);
            }
        }catch(IOException e){
    
    
            e.printStackTrace();
        }
    }
}

单个文件复制

    public static void test01() throws IOException {
    
    
        InputStream is = null;
        OutputStream os = null;
        try {
    
    
            // 如果读取文件不存在,FileNotFoundException
            is = new FileInputStream("c:\\test\\oss2.zip");
            // 如果输出文件不存在,会自动创建文件,如果存在,会覆盖
            os = new FileOutputStream("c:\\test\\oss.zip");
            int data=-1;
            //  每次read()方法默认读取一个字节 可设置读取单位为[1024*1024]
            byte[] buffer = new byte[1024*1024];
            while((data=is.read(buffer))!=-1){
    
    
                System.out.println(data);
                os.write(buffer,0, data);
            }
            System.out.println("文件复制成功");
        } catch (FileNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }finally{
    
    
            os.close();
            is.close();
        }
    }

递归复制目录下所有文件到目标目录

public class Test01 {
    
    
    public static void main(String[] args) {
    
    
        copyFile("C:/software","c:/backup");
    }
    public static void copyFile(String srcPath, String destPath) {
    
    
        File srcFile = new File(srcPath);
        File destFile = new File(destPath);
        
        if(srcFile.isDirectory()){
    
    
            destFile=new File(destPath+File.separator+srcFile.getName());
            destFile.mkdirs();
            
            File[] files = srcFile.listFiles();
            for (File file : files) {
    
    
                copyFile(file.getAbsolutePath(), destFile.getAbsolutePath());
            }
        }else if(srcFile.isFile()){
    
    
            try(
                InputStream is=new FileInputStream(srcFile);
                OutputStream os=new FileOutputStream(destPath+File.separator+srcFile.getName());
            ){
    
    
                byte[] buffer=new byte[1024*1024];
                int num=-1;
                while((num=is.read(buffer))!=-1){
    
    
                    os.write(buffer, 0, num);
                }
                System.out.println("复制"+srcPath);
            }catch(IOException e){
    
    
                e.printStackTrace();
            }
        }
    }
}

文件的拆分和合并

public class Test01 {
    
    
    public static void main(String[] args) {
    
    
        // 路径不包含bak的话报错,不知为何,总之不能在根目录下操作
        splitFile("C:\\bak\\oss.zip");
        mergeFile("C:\\bak\\oss.zip_1");
    }
    // 拆分文件:一个输入流,多个输出流
    public static void splitFile(String filePath) {
    
    
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
    
    
            fis = new FileInputStream(filePath);
            byte[] buffer = new byte[1024 * 1024 * 10]; // 每次读取10M
            int num = -1;
            int index = 0;
            while ((num = fis.read(buffer)) != -1) {
    
    
                fos = new FileOutputStream(filePath + "_" + (++index));
                fos.write(buffer, 0, num);
                fos.flush();
                fos.close();
            }
            System.out.println("拆分成功,共拆分为:" + index + "个");
        } catch (FileNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if (fis != null) {
    
    
                try {
    
    
                    fis.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }
    // 合并文件:一个输出流,多个输入流
    public static void mergeFile(String filePath) {
    
     //filePath只需要一个文件名,通过截取即可
        String basePath = filePath.substring(0, filePath.lastIndexOf("_"));
        FileOutputStream fos = null;
        FileInputStream fis = null;
        try {
    
    
            fos = new FileOutputStream(basePath);
            int index = 1;
            File f = null;
            while ((f = new File(basePath + "_" + index++)).exists()) {
    
    
                fis = new FileInputStream(f);
                byte[] buffer = new byte[fis.available()];
                fis.read(buffer);
                fos.write(buffer);
                fos.flush();
                fis.close();
            }
            System.out.println("合并成功:"+basePath);
        } catch (FileNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if (fos != null) {
    
    
                try {
    
    
                    fos.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/vayne_xiao/article/details/111056375