Java IO流-输入输出、序列化与反序列化、标准输入输出、打印流等

1. 数据输入输出流

  • 概述

    • 用来对Java中的基本数据类型进行操作
    • 可以写基本数据类型,也可以读基本数据类型
  • 分类

    • 数据输入流
      • DataInputStream
    • 数据输出流
      • DataOutputStream
  • 练习

    • 使用数据输入输出流
    public class Test {//数据输入输出流演示
    
        public static void main(String[] args) throws IOException {
            DataOutputStream output = new DataOutputStream(new FileOutputStream("Info.txt"));//创建数据输出流
            output.writeUTF("123456");//写入字符串
            output.writeChar('你');//写入字符
            byte[] bytes = {9, 8, 7, 6, 5};
            output.write(bytes);//写入字节数组
            output.close();//关闭数据输出流
    
            DataInputStream input = new DataInputStream(new FileInputStream("Info.txt"));//创建数据输入流
            String s = input.readUTF();//读取字符串
            System.out.println(s);
            char c = input.readChar();//读取字符
            System.out.println(c);
            byte[] bytes1 = new byte[5];
            input.read(bytes1);//读取字节数组
            System.out.println(bytes1);
            input.close();//关闭数据输入流
        }
    }
  • 注意

    • 写入的数据类型顺序与读出的数据类型顺序应保持一致

2. 内存操作流

  • 概述
    • 针对内存进行操作的流
  • 分类
    • 操作字节数组
      • ByteArrayOutputStream
      • ByteArrayInputStream
    • 操作字符数组
      • CharArrayWrite
      • CharArrayReader
    • 操作字符串
      • StringWriter
      • StringReader

3. 打印流

  • 概述

    • 向文本输出流打印对象的格式化表示形式,将数据打印到某个文件或设备,能直接对文件及逆行操作
  • 打印流特点

    • 只能操作目的地,不能操作源数据,也就是不能读取数据,但是可以写入数据
    • 可以写入任何数据类型的数据,调用print() 方法
    • 可以启动自动刷新,启动后当调用println、printf、format方法中的一个时,会自动进行刷新
    • 可以直接对文件进行操作
  • PrintWriter

    • 构造方法
      • public PrintWriter(OutputStream out,boolean autoFlush)
      • public PrintWriter(Writer out,boolean autoFlush)
  • 练习

    • 使用打印流实现文本文件复制
    public class PrintFileCopy {//使用字符打印流复制文件
        
        public static void main(String[] args) throws IOException {
            BufferedReader buffReader = new BufferedReader(new FileReader("Student.java"));
            PrintWriter printWriter = new PrintWriter(new FileWriter("Student-副本.java", true));
            //创建高效字符流与打印流,并打开打印流的自动刷新
    
            String result;
            while ((result = buffReader.readLine()) != null) {
                printWriter.println(result);
            }
            buffReader.close();
            printWriter.close();
        }
    }

4. 标准输入输出流

  • 概述

    • 在System类中有两个静态成员变量,分别对应键盘的录入与显示器的输出
    • public static final InputStream in
      • 标准输入流,对应的是键盘的输入
    • public static final PrintStream out
      • 标准的输出流,对应的是显示屏的输出
  • 两种方法实现键盘录入

    • in和out的类型

      • System.in
        • 是InputStream类型
      • System.out
        • 是OutputStream的子类型
    • 使用Scanner录入

      public static void main(String[] args) {
              Scanner scanner = new Scanner(System.in);
              System.out.println("请输入你的姓名");
              String name = scanner.next();
          }
    • 使用BufferedReader的readLine方法

      public class InOutDemo {//使用高效字符输入输出流关联键盘与屏幕
          
          public static void main(String[] args) throws IOException {
              //System.in是InputStream下的子类
              //System.out是OutputStream下的子类
      
              BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));//将高效字符输入流与键盘关联
              System.out.println("请输入你的姓名");
              String name = reader.readLine();//获得键盘输入
      
              BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));//将高效字符输出流与显示屏关联
              writer.write(name);//将姓名打印到显示屏上
              writer.flush();//字符流需要刷一下
          }
      }

5. 随机访问流

  • 概述

    • 支持对文件的读和写操作,内部含有一个文件指针,在读文件时,随着对字节的写入指针也在后移,可以记录某一时刻指针的位置,使得下一次读取文件从指定位置开始。常用于缓存暂停等场景
    • 不属于流,是Object类的子类,但是有InputStream和OutputStream的功能
  • 构造方法

    • RandonAccessFile(File file,String mode)
      • 创建一个可读可写的随机的访问文件流,后面的参数是r表示可读,是rw表示可读可写
    • RandomAccessFile(String name,String mode)
      • 创建一个可读可写的随机访问文件流,参数二同上
  • 方法

    • read系列
      • 可以从文件中读取某一类型的数据
    • write系列
      • 可以向文件中写入某一类型的数据
    • void seek (long pos)
      • 设置文件指针的位置,
    • long getFilePointer()
      • 得到当前文件指针的位置,使得下一次的读取操作从此位置开始
  • 练习

    • 使用RandomAccessFile复制文件
    public class MusicCopies {//使用RandomAccessFile将歌曲复制三份
    
        public static void main(String[] args) throws IOException {
            
            RandomAccessFile inputFile = new RandomAccessFile("许巍 - 曾经的你.mp3", "rw");//创建随机访问输入流,与原文件关联
            RandomAccessFile outputFile = null;//创建随机访问输出流
            
            for (int i = 0; i < 3; i++) {
                int len = 0;
                byte[] bytes = new byte[1024 * 8];
                outputFile = new RandomAccessFile(i + "许巍 - 曾经的你.mp3", "rw");
                while ((len = inputFile.read(bytes)) != -1) {
                    outputFile.write(bytes, 0, len);
                }
                inputFile.seek(0);//每复制一次,将指针置为0
                outputFile.close();
            }
            inputFile.close();
        }
    }

6. 序列化流与反序列化流

  • 概述

    • 用来对对象和基本数据类型进行读写,序列化是将对象通过流的方法写入文件中,反序列化是将对象从文件中读取出来
    • 序列化流
      • ObjectOutputStream
        • 将对象序列化转换为字节流
    • 反序列化流
      • ObjectInputStream
        • 将对象字节流反序列化转换为对象
  • ObjectOutputStream和ObjectInputStream特有方法

    • ObjectOutputStream: void writeObject(Object obj)
      • 将对象写入
    • ObjectInputStream:Object readObject()
      • 从文件中读取到对象
  • 自定义类序列化

    • 只有类实现了Serializable接口,这个类的对象才能被序列化
    • 序列化以后,在序列化文件中还存在一个标记serialVersionUID,在进行反序列化之前,程序会验证当前的标记与序列化文件中的标记是否一致,如果一致会进行序列化,不一致会报错(不一致是因为在序列化后又修改了类)
    • 解决标记不一致报错的方案
      • 将这个标记显式的给出来,这样子这个标记就不会变了
      • private static final long serialVersionUID =-6150L;
      • 可以强制提示给出标记
  • 如何让成员变量不被序列化

    • 使用transient关键字,加上关键字的成员变量将不会被序列化
  • 练习

    • 使用ObjectOutputStream与ObjectInputStream对自定义类的对象序列化与反序列化
    public class Student implements Serializable {//自定义学生类
        public static final long serialVersionUID = 42L;//给定标记
        private String name = "";
        private int age = 0;//成员变量
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public Student() {
        }
    
        public Student(String name, int age) {//有参构造
            this.name = name;
            this.age = age;
        }
    }
    
    public class ObjectStreams {//对自定义类的对象序列化与反序列化
    
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            Student zhangSan = new Student("张三", 23);//创建自定义类对象
            ObjectOutputStream outStream = new ObjectOutputStream(new FileOutputStream("student.txt"));//创建序列化流
            outStream.writeObject(zhangSan);//将对象写入
            outStream.flush();
            outStream.close();//关闭序列化流
    
            Object o = new ObjectInputStream(new FileInputStream("student.txt")).readObject();//创建反序列化流并得到其中存储的对象
            zhangSan = (Student) o;
            System.out.println(zhangSan.getName());
            System.out.println(zhangSan.getAge());//打印对象的成员变量
        }
    }

7. Properties集合

  • 概述

    • Properties集合是双列集合,父类是Hashtable,集合中的元素以键值对的形式存储,可以从键值对文件中直接获取键值对到集合中,也可以将集合中的元素以键值对的形式写入关联文件中
  • 特有方法

    • public Object setProperty(String key,String vaule)
      • 将元素以键值对的形式存入集合中
    • public String getproperty(String key)
      • 根据键得到元素的值
    • public Set stringPropertyNames()
      • 得到集合中所有的键的集合
    • void load(Reader reader)
      • 将关联文件中的键值对元素加载进集合中
    • void store (Writer writer,String comments)
      • 将集合中的元素以键值对的形式存储进关联文件中
  • 练习

    • 判断指定文件中是否有指定的键,如果有,修改文件中该键所对应的值
    public class ReviseVaule {//判断文件中是否有指定的键,如果有,改变键对应的值
    
        public static void main(String[] args) throws IOException {
            /*需求:我有一个文本文件file.txt,我知道数据是键值对形式的,但是不知道内容是什么。
            请写一个程序判断是否有 "lisi" 这样的键存在,如果有就改变其实为 "100"
            file.txt文件内容如下:
            zhangsan = 90
            lisi = 80
            wangwu = 85*/
    
            Properties personInfo = new Properties();//创建双列集合,用来存储键值对
    
            personInfo.load(new FileInputStream("file.txt"));//将集合与键值对文件关联
            for (String name : personInfo.stringPropertyNames()) {//得到所有键的集合并遍历
                if (name.equals("lisi")) {//如果键等于"lisi",就将该键所对应的值改为100
                    personInfo.setProperty("lisi", "100");
                }
            }
            personInfo.store(new FileOutputStream("file.txt"), "修改过后的值");//将修改过后的值重新写入文件中
        }
    }

8. SequenceInputStream

  • 概述

    • 可以将其他的流逻辑串联起来,实现文件的合并
  • 构造方法

    • SequenceInputStream(InputStream s1, InputStream s2)
  • 练习

    • 将两首歌曲合并
    public class MusicCopy {//将两首歌曲合并
        public static void main(String[] args) throws IOException {
            SequenceInputStream inputStream = new SequenceInputStream(new FileInputStream("许巍 - 蓝莲花.mp3"), new FileInputStream("许巍 - 曾经的你.mp3"));//将两个歌曲文件合并,得到合并后的字节
            FileOutputStream outputStream = new FileOutputStream("C:\\Users\\北风\\Desktop\\歌曲合并.mp3");//创建字节输出流
    
            byte[] bytes = new byte[1024 * 8];
            int len;
            while ((len = inputStream.read(bytes)) != -1) {//将合并后的字节写出
                outputStream.write(bytes, 0, len);
            }
            inputStream.close();
            outputStream.close();//关闭流
        }
    }

9. 压缩流与解压流

  • ZipOutputStream
    • 压缩流
    • void putNextEntry(ZipEntry e)
      • 开始写入新的 ZIP 文件条目并将流定位到条目数据的开始处。
  • ZipInputStream
    • 解压流
    • ZipEntry getNextEntry()
    • 读取下一个 ZIP 文件条目并将流定位到该条目数据的开始处。
  • ZipEntry类
    • 此类用于表示 ZIP 文件条目。
    • String getName()
      • 返回条目名称
    • boolean isDirectory()
      • 如果为目录条目,则返回 true
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值