Java 文件读取和写入多个对象

在开始整理文件读取和写入对象之前,先回顾一下文件读取和写入的内容:


字符流与字节流

1. 字符流

传输过程中,传输数据的最基本单位是字符的流

通过 BufferedReader 读取文件内容:

public static void readFile() throws IOException {
	Path path = Paths.get("data.txt");
	BufferedReader reader = Files.newBufferedReader(path);
	String lineContent = reader.readLine();
	while (lineContent != null) {
		System.out.println(lineContent);
		lineContent = reader.readLine();
	}
	reader.close();
}

BufferedReader : 由 Reader 类扩展而来,提供通用的缓冲方式文本读取来提高效率,而且提供了很实用的 readLine() 方法

通过 BufferedWriter 向文件中写入:

public static void writeFile(String[] data) throws IOException {
	Path path = Paths.get("data.txt");
	BufferedWriter writer = Files.newBufferedWriter(path);
	for (int i=0;i<data.length;i++) {
		writer.write(data[i]);
		writer.newLine();
	}
	writer.close();
}

2. 字节流

传输过程中,传输数据的最基本单位是字节的流

通过 BufferedInputStream 读取文件内容:

public static void readFile() throws IOException {
	FileInputStream file = new FileInputStream("data.txt");
	BufferedInputStream reader = new BufferedInputStream(file);
	byte[] buff = new byte[MAX_SIZE];
	while ((len  = reader.read(buff)) != -1) {
		System.out.println(new String(buff, 0, len));
	}
	reader.close();
	file.close();
}

new String(byte bytes[], int offset, int length, String charsetName); : 通过指定字符集对二进制数组进行编码,并转换成字符串形式。

通过 BufferedOutputStream 向文件中写入:

public void writeFile(String data) throws IOException {
	FileOutputStream file = new FileOutputStream("data.txt");
	BufferedOutputStream writer = new BufferedOutputSream(file);
	writer.write(data.getBytes());
	writer.close();
	file.close();
}

BufferedInputStreamBufferedOutputStream : 一种通过封装其它流来提高效率的流,所以使用前需要先实例化一个其它的流。

3. 字符流和字节流的区别

从本质上来讲,不管是读还是写数据,都是将二进制以字节为单位进行存取操作。字节流就是直接以二进制形式读取或写入文件内容,我们如果想要知道读取的内容,需要指定一种编码方式,写入时则需要转换成 Byte 类型。而字符流则自带了一种编码,所以读取和写入时不需要我们手动转换,而且基本的单位是以字符的大小为标准。


对象的读取和写入

想要对对象进行读取和写入文件的操作,需要让该对象先实现一个接口 Serializable

Serializablejava.io 包中定义的、用于实现类的序列化操作而提供的一个语义级别的接口。Serializable 接口没有任何方法或者字段,只是用于标识可序列化的语义。实现了 Serializable 接口的类可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型,它可以被 ObjectOutputStream 转换为字节流,同时也可以通过 ObjectInputStream 再将其解析为对象。

1. 读取一个对象

public void readObject() throws IOException, ClassNotFoundException {
	FileInputStream file = new FileInputStream(new File("data.txt"));
	ObjectInputStream reader = new ObjectInputStream(file);
    YourClassName Cls = (YourClassName) reader.readObject();
    file.close();
    reader.close();
}

2. 写入一个对象

public void writeObject(YourClassName Data) throws IOException {
	FileOnputStream file = new FileOnputStream(new File("data.txt"));
	ObjectOnputStream writer = new ObjectOnputStream(file);
    writer.writeObject(Data);
    file.close();
    reader.close();
}

3. 读取多个对象

public List readMulObject() throws IOException {
    List<Student> lst = new ArrayList<>();
    FileInputStream file = new FileInputStream(new File("data.txt"));
	ObjectInputStream reader = new ObjectInputStream(file);
    while (true) {
        try {
            YourClassName Cls = (YourClassName) reader.readObject();
            lst.add(Cls);
        } catch (EOFException e) {
        	System.out.println("读取完成");
        	break;
        }
    }
   	file.close();
   	reader.close();
    return lst;
}

4. 写入多个对象

public void writeFile(List<YourClassName> lst) throws IOException {
	FileOutputStream file = new FileOutputStream(new File("data.txt"));
    ObjectOutputStream writer = new ObjectOutputStream(file);
    for (YourClassName Cls : lst) {
        writer.writeObject(Cls);
    }
    writer.close();
}

这里有一个问题,在写入对象时,默认会从文件开头开始写入,这样会覆盖文件原本的内容。想在文件后部追加写入的话,需要 FileOutputStream file = new FileOutputStream(new File("data.txt"), 1) 但这样又会有一个问题:在每次打开文件时,程序会默认在写入信息之前加一个 ACED 0005 字段,但在读取的时候,会误认为它是对象的一部分,导致解析出错。这个问题我目前还没有发现完善的解决方案,现在采取的措施是,在写入文件前,先用 List 把内容全部取出,然后写入的信息全部加到 List 里,再把 List 一整个存入文件。

上一篇:bat隐藏窗口运行


下一篇:.net core 使用Redis的发布订阅