JavaSE——IO流(四)数据输入输出流,内存操作流,打印流,序列化流,随机访问流,Properties

1.DateInputStream和DateOutputStream

(1)概述

数据输入流: DataInputStream
数据输出流: DataOutputStream
特点: 可以写基本数据类型,可以读取基本数据类型。

(2)案例演示
package com.wetstmo.demo.demo2;
import java.io.*;
public class MyDemo7 {
    public static void main(String[] args) throws IOException {
        //可以读写基本数据类型
        DataOutputStream out = new DataOutputStream(new FileOutputStream("a.txt"));
        out.writeInt(123);
        out.writeBoolean(true);
        out.writeChar('c');
        out.close();
        //注意:读的顺序要和写的顺序一致
        DataInputStream in = new DataInputStream(new FileInputStream("a.txt"));
        System.out.println(in.readInt());
        System.out.println(in.readBoolean());
        System.out.println(in.readChar());
        in.close();
    }
}

2.内存操作流

(1)概述

内存操作流只在内存中操作,不直接关联文件。

操作字节数组
		ByteArrayOutputStream
		ByteArrayInputStream   
		此流关闭无效,所以无需关闭
操作字符数组
		CharArrayWrite
		CharArrayReader
操作字符串
		StringWriter
		StringReader	
(2)案例演示
package com.wetstmo.demo.demo2;
import java.io.*;
public class MyDemo8 {
    public static void main(String[] args) throws IOException {
        //此类实现了一个输出流,其中的数据被写入一个byte数组,
        //这个缓冲区会随着数据的不断写入而自动增长
        //可以使用toByteArray()和toString()来获取数据
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        out.write("哈哈哈哈哈".getBytes());
        out.write("qweqwe".getBytes());
        //取出此流所维护的字节数
        byte[] bytes = out.toByteArray();
        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        //创建一个数组作为缓冲数组来读取
        int len=0;
        byte[] bytes1 = new byte[1024 * 8];
        len = in.read(bytes1);
        String s = new String(bytes1,0,len);
        System.out.println(s);
        //此流无需关闭
        //底层维护的缓冲区的字符数组
        CharArrayWriter writer = new CharArrayWriter();
        writer.write("adawda");
        writer.write("你好呀");
        String s1 = writer.toString();
        System.out.println(s1);
        CharArrayReader reader = new CharArrayReader(writer.toCharArray());
        int read = reader.read();
        System.out.println(read);
        //此流底层使用的是StringBuffer
        StringWriter stringWriter = new StringWriter();
        stringWriter.write("武汉加油");
        String s2 = stringWriter.toString();
        System.out.println(s2);
    }
}

3.打印流

(1)打印流的特点
  • 打印流只能操作目的地,不能操作数据源(不能进行读取数据)
  • 可以操作任意数据类型的数据 调用print() 方法可以写任意数据类型
  • 如果我们启用自动刷新,那么在调用println、printf 或 format 方法中的一个方法的时候,会完成自动刷新。
  • 启动自动刷新的方法
public PrintWriter(OutputStream out,  boolean autoFlush)	 启动 自动刷新 
public PrintWriter(Writer out,  boolean autoFlush)		启动自动刷新
(2)使用打印流完成文件赋值
package com.wetstmo.demo.demo2;
import java.io.*;
public class MyDemo9 {
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new FileReader("SortArray.java"));
        PrintWriter printWriter = new PrintWriter(new FileOutputStream("Sort.java",true));//自动刷新
        String len=null;
        while ((len = bufferedReader.readLine()) != null) {
            printWriter.println(len);
        }
        bufferedReader.close();
        printWriter.close();
    }
}

4.标准输入输出流理解

(1)概述

在System这个类中存在两个静态的成员变量:

 public static final InputStream in: 标准输入流, 对应的设备是键盘
 public static final PrintStream out: 标准输出流 , 对应的设备就是显示器

System.in的类型是InputStream。System.out的类型是PrintStream是OutputStream的孙子类,FilterOutputStream 的子类。

(2)两种方式实现键盘录入
package com.wetstmo.demo.demo2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
public interface MyDemo10 {
    public static void main(String[] args) throws IOException {
        //第一种方式
        InputStream in = System.in;
        Scanner scanner = new Scanner(in);
        int i = scanner.nextInt();
        System.out.println(i);
        //第二种方式
        InputStream in1 = System.in;
        InputStreamReader inputStreamReader = new InputStreamReader(in1);
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String s = bufferedReader.readLine();
        System.out.println(s);
    }
}

5.随机访问流

(1)概述
RandomAccessFile概述 最大特点 能读能写
RandomAccessFile类不属于流,是Object类的子类。但它融合了InputStream和OutputStream的功能。
支持对随机访问文件的读取和写入。
(2)特点
  • RandomAccessFile的父类是Object , 这个流对象可以用来读取数据也可以用来写数据.可以操作任意数据类型的数据.
  • 我们可以通过getFilePointer方法获取文件指针,并且可以通过seek方法设置文件指针
  • 随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针
(3)构造方法
RandomAccessFile(File file, String mode)
创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。
RandomAccessFile(String name, String mode)
创建从中读取和向其中写入(可选)的随机访问文件流,
该文件具有指定名称。
案例演示
package com.wetstmo.demo.demo1;
import java.io.IOException;
import java.io.RandomAccessFile;
public class MyDemo2 {
    public static void main(String[] args) throws IOException {
        RandomAccessFile random1 = new RandomAccessFile("火箭少女101 - 卡路里.mp3", "rw");
        RandomAccessFile random2 = new RandomAccessFile("火箭少女102 - 卡路里.mp3", "rw");
        byte[] bytes = new byte[1024];
        int len=0;
        while ((len = random1.read(bytes)) != -1) {
            random2.write(bytes,0,len);
        }
        random1.close();
        random2.close();
        //下次开始的时候,可以把指针设置到上次暂停的位置
        //random1.seek(1000);
        //random2.seek(1000);
    }
}

6.序列化流和反序列化流

(1)概述
  • 序列化:ObjectOutputStream,就是把对象通过流的方式存储到文件中,注意此对象要实现Serializable 接口才能被序列化。
  • 反序列化:ObjectInputStream,就是把文件中存储的对象以流的方式还原成对象
(2)案例演示
package com.wetstmo.demo.demo1;
import java.io.*;
public class MyDemo3 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //序列化();
        反序列化();
    }
    private static void 序列化() throws IOException {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("b.txt"));
        Student student = new Student("张三", 89);
        Student student1 = new Student("王五", 23);
        out.writeObject(student);
        out.writeObject(student1);
        out.close();
    }
    private static void 反序列化() throws IOException, ClassNotFoundException {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("b.txt"));
        Student s1 = (Student) in.readObject();
        Student s2 = (Student) in.readObject();
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s1.getName() + s1.getAge());
        System.out.println(s2.getName() + s2.getAge());
        in.close();
    }
}
class Student implements Serializable {
    private String name;
    private int age;
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    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;
    }
}

我们的一个类可以被序列化的前提是需要这个类实现Serializable接口,就需要给这个类添加一个标记.
在完成序列化以后,序列化文件中还存在一个标记,然后在进行反序列化的时候。
会验证这个标记和序列化前的标记是否一致,如果一致就正常进行反序列化,如果不一致就报错了. 而现在我们把这个类做了修改,将相当于更改了标记,而导致这两个标记不一致,就报错了。

会报如下的错误

Exception in thread "main" java.io.InvalidClassException: com.wetstmo.demo.demo1.Student; local class incompatible: stream classdesc serialVersionUID = 6583765957677158843, local class serialVersionUID = 1685286942524183227
	at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1843)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1713)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2000)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1535)

解决办法:只要让这两个的标记一致,就可以,所以我们可以添加一个这个:
private static final long serialVersionUID = -7602640005373026150L;

4.如何让对象的成员变量不被序列化
  • 使用transient关键字声明不需要序列化的成员变量
    例如:private transient int age ;// 可以阻止成员变量的序列化使用transient

7.Properties

(1)概述

Properties 类表示了一个持久的属性集。
Properties 可保存在流中或从流中加载。
属性列表中每个键及其对应值都是一个字符串。
Properties父类是Hashtable
属于双列集合,这个集合中的键和值都是字符串 Properties不能指定泛型

(2)使用
public Object setProperty(String key,String value)
public String getProperty(String key)
public Set stringPropertyNames()
public void load(Reader reader): 读取键值对数据把数据存储到Properties中
public void store(Writer writer, String comments)把Properties集合中的键值对数据写入到文件中, comments注释
(3)案例演示
package com.wetstmo.demo.demo1;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
public class MyDemo4 {
    public static void main(String[] args) throws IOException {
        Properties properties = new Properties();
        properties.setProperty("username","张三");
        properties.setProperty("password","123456");
        //将简直数据存储到文件中,键值之间以等号连接
        properties.store(new FileWriter("a.properties"),null);
        //把文件中的键值数据读回集合
        Properties properties1 = new Properties();
        properties1.load(new FileReader("a.properties"));
        System.out.println(properties1);
    }
}

8.SequenceInputStream

(1)概述

表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

(2)构造方法
SequenceInputStream(InputStream s1, InputStream s2) 
	通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。
SequenceInputStream(Enumeration e) 
	 通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。
(3)将两个文件合成一个文件
package com.wetstmo.demo.demo1;
import java.io.*;
public class MyDemo5 {
    public static void main(String[] args) throws IOException {
        FileInputStream inputStream = new FileInputStream("火箭少女101 - 卡路里.mp3");
        FileInputStream inputStream1 = new FileInputStream("无限王者团 - 千灯之约.mp3");
        SequenceInputStream sequenceInputStream = new SequenceInputStream(inputStream, inputStream1);
        FileOutputStream fileOutputStream = new FileOutputStream("111.mp3");
        int len=0;
        byte[] bytes = new byte[1024 * 8];
        while((len=sequenceInputStream.read(bytes))!=-1){
            fileOutputStream.write(bytes,0,len);
            fileOutputStream.flush();
        }
        sequenceInputStream.close();
        fileOutputStream.close();
    }
}

9.综合练习

将一个文件复制多份
package com.wetstmo.demo.一个文件复制多份;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
public class MyDemo {
    public static void main(String[] args) throws IOException {
        RandomAccessFile rw = new RandomAccessFile("SortArray.java", "rw");
        File file = new File("E:\\123");
        for (int i = 0; i < 5; i++) {
            FileOutputStream fileOutputStream = new FileOutputStream(new File(file, i + ".java"));
            int read=0;
            byte[] bytes = new byte[1024 *8];
            while((read=rw.read(bytes))!=-1){
                fileOutputStream.write(bytes,0,read);
                fileOutputStream.flush();
            }
            fileOutputStream.close();
            rw.seek(0);
        }
        rw.close();
    }
}

你可能感兴趣的:(JavaSE)