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
    评论
### 回答1: 序列化数组是将数组对象转换为字节流的过程,以便在网络上传输或保存到文件中。Java提供了对象IO流来实现序列化反序列化操作。要序列化数组,需要将数组对象包装在一个对象中,然后使用ObjectOutputStream将对象写入字节流。反序列化时,使用ObjectInputStream将字节流读取为对象,然后从对象中获取数组。需要注意的是,数组中的每个元素都必须是可序列化对象。 ### 回答2: Java输入输出(IO)流是Java应用程序中非常重要的一部分,它可以基于二进制流或字符流来输入或输出数据。对象IO流Java IO流中的一种重要形式,可以用来处理Java对象Java对象可以被序列化并写入文件中,以便在需要时读取。 序列化是将对象转换为字节序列的过程,以便可以将它们存储在磁盘上或在网络上传输。反序列化是将字节序列转换回对象的过程。使用Java序列化,可以将对象保存在文件中,然后在以后读取它们,或者在不同的机器之间传递对象序列化数组是将数组的所有元素序列化到文件中或者在网络上传输的过程。Java提供了多种序列化方法来序列化数组。以下是使用对象IO流进行序列化数组的步骤: 1. 创建一个需要序列化对象数组。例如,int[] array = {1, 2, 3, 4, 5}。 2. 创建一个输出流,可以使用文件输出流或套接字输出流,以便将字节数据写入文件或通过网络传输。 3. 创建序列化对象,将输出流对象作为参数传入。例如,ObjectOutputStream oos = new ObjectOutputStream(fos)。 4. 调用序列化对象的writeObject()方法来将数组对象序列化并写入输出流中。例如,oos.writeObject(array)。 5. 使用flush方法刷新缓冲区。 6. 序列化流和输出流。例如,oos.close()和fos.close()。 7. 创建一个输入流,可以使用文件输入流或套接字输入流,以便从文件或网络接收字节数据。 8. 创建反序列化对象,将输入流对象作为参数传入。例如,ObjectInputStream ois = new ObjectInputStream(fis)。 9. 调用反序列化对象的readObject()方法,将字节数据读取为数组对象。例如,int[] newArray = (int[]) ois.readObject()。 10. 使用读取的数组对象进行必要的操作。 11. 反序列化流和输入流。例如,ois.close()和fis.close()。 在使用Java对象IO流进行序列化反序列化时,需要注意以下事项: 1. 需要序列化对象必须实现Serializable接口,该接口没有任何具体方法,只是将您的类标记为可序列化的类。 2. 如果不希望某些类的某些实例被序列化,可以使用transient键字。 3. 在序列化反序列化时,需要确保使用相同的序列化序列。如果序列化序列不同,反序列化将失败。 4. 序列化反序列化可能会引起性能问题,因此需要在性能需求和数据安全性之间进行权衡。 ### 回答3: 在Java编程中,I/O流是非常重要的概念,它可以将数据从硬盘或网络读取到内存中,或将内存中的数据写入到硬盘或网络中,从而实现数据的交换。I/O流非常灵活,无论是读取文件、网络数据,还是处理用户输入等,都必不可少。而序列化则是I/O流的一种特殊形式,可以将Java对象转换成二进制的形式,以便在网络上进行传输或存储到硬盘中保存,同时也可以将二进制数据转换回Java对象Java序列化的过程中,我们可以将一个对象的所有属性都存储在一个数组中,这就是数组序列化。数组序列化非常灵活,我们可以将多个不同类型的对象存储在同一个数组中,在需要的时候从数组中读出来进行处理。数组序列化也非常适合用来存储表格、矩阵、图像等数据。 Java中的数组序列化可以通过使用ObjectOutputStream和ObjectInputStream类来实现。ObjectOutputStream类可以将Java对象序列化为二进制数据输出流,而ObjectInputStream类可以将输入流中的二进制数据反序列化Java对象。在进行序列化之前,必须保证对象中的所有成员变量都是可序列化的,否则将会抛出NotSerializableException异常。 实现数组序列化的步骤如下: 1. 创建数组对象,并初始化数组; 2. 创建ObjectOutputStream对象,并调用writeObject()方法将数组序列化到输出流中; 3. 创建ObjectInputStream对象,从输入流中读取二进制数据,并调用readObject()方法将数据反序列化Java对象; 4. 闭流。 下面是一个简单的数组序列化的样例代码: ```java import java.io.*; public class ArraySerialization { public static void main(String[] args) { int[] arr = {1, 2, 3, 4, 5}; try { // 创建ObjectOutputStream对象 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("array.ser")); // 序列化数组对象到输出流中 out.writeObject(arr); out.close(); // 创建ObjectInputStream对象 ObjectInputStream in = new ObjectInputStream(new FileInputStream("array.ser")); // 从输入流中反序列化Java对象 int[] newArr = (int[]) in.readObject(); for (int i = 0; i < newArr.length; i++) { System.out.print(newArr[i] + " "); } in.close(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } ``` 以上是一个数组序列化的简单样例,实际应用中还需要针对具体情况做调整,并且要注意处理可能出现的异常。总之,数组序列化Java I/O流的一个重要方面,它可以方便地将多个数据存储到一个数组中,并在需要的时候进行读取和处理,同时也是Java数据持久化的一个重要手段。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值