没有任何内容被写入到 .dat 文件中。

huangapple go评论78阅读模式
英文:

Nothing being written to a .dat file

问题

我正在尝试创建一个程序,用于读取包含HashMap对象的.dat文件。如果.dat文件为空,它应该将一个空的HashMap对象写入文件,然后应该给用户提供选项来编辑HashMap对象。

当我第一次尝试对一个空的.dat文件“playlist.dat”进行此操作时,它试图将一个空的HashMap对象写入文件,但随后触发了一个EOFException异常。我查看了文件,发现它是空的。

处理此问题的代码如下:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Scanner;

@SuppressWarnings("unchecked") // 这是阻止发生“Type safety: Unchecked cast from Object to HashMap<String,Song>”错误的唯一方法

public class Main {
    public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
        // 歌曲映射
        HashMap<String, Song> playList = new HashMap<String, Song>();

        // 获取存储位置的文件名
        Scanner input = new Scanner(System.in);
        System.out.print("请输入您存储/将要存储播放列表的文件名:");
        String fileName = input.nextLine();
        input.close();

        File file = new File(fileName);

        ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file))); // 使用输出流找到用户请求的文件

        if (file.length() == 0) {
            out.writeObject(playList);
        } // 检查文件是否为空,如果是,则写入空的HashMap

        ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file))); // 这是发生EOFException异常的地方。在上面的if语句中,它测试文件是否为空。由于playlist.dat是空的,它将尝试将空的HashMap播放列表写入文件,但由于发生EOFException并且playlist.dat是空的,显然没有成功。

        playList = (HashMap<String, Song>) in.readObject();
        System.out.println("正在打开位于 " + fileName + " 的播放列表。");
        in.close();

        /* 其他代码继续... */
    }
}
英文:

I am trying to create a program that reads a .dat file containing a HashMap object. If the .dat file is empty, it should write an empty HashMap object to the file, then, it should give the user options to edit the HashMap object.

When I tried this for the first time with an empty .dat file "playlist.dat", it attempted to write an empty HashMap object to the file, but then triggered an EOFException. I looked in the file and saw that it was empty.

The code handling this is here:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Scanner;

@SuppressWarnings(&quot;unchecked&quot;) //was the only way to stop the error: &quot;Type safety: Unchecked cast from Object to HashMap&lt;String,Song&gt;&quot; from happening

public class Main {
	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
		// Map of songs
		HashMap&lt;String, Song&gt; playList = new HashMap&lt;String, Song&gt;();

		// getting file name where it is stored
		Scanner input = new Scanner(System.in);
		System.out.print(&quot;Enter the file name you stored/will store your playlist in: &quot;);
		String fileName = input.nextLine();
		input.close();

		File file = new File(fileName);
		
		ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file))); //using output streams to find the file requested by user

		if (file.length() == 0) {
			out.writeObject(playList);
			//System.out.println(&quot;Wrote playlist&quot;); //debug
		} //sees if there is nothing in the file, and if there is nothing, writes a blank HashMap to it

		ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file))); //This is where the EOFException is taking place. In the if statement above, it tests if the file is empty. Since playlist.dat is empty, it will attempt to write an empty HashMap playlist to the file, but since there is an EOFException and playlist.dat is empty, it is clearly not doing this.
		
		playList = (HashMap&lt;String, Song&gt;) in.readObject();
		System.out.println(&quot;Opening playlist at &quot; + fileName + &quot;.&quot;); //debug
		in.close();

/* other code continues this way... */

答案1

得分: 0

一些事情:

  1. 对象流非常脆弱且不理想。使用不同版本的Java的用户可能无法在与对象序列化版本不同的版本中打开你的HashMap。相反,我建议使用XML(已包含在JRE中)或JSON(我认为你需要Jackson库...除非它已添加到JRE中)。

  2. 你不需要缓冲输入或输出流。首先,缓冲流用于低效的读写(比如按行读取,或者(不一次性地)写入文件)。但是对象流和PrintWriter / PrintStream(虽然你没有在使用,但我为了完整性已经包含在内)已经内置了缓冲能力。

  3. 在尝试从流中读取内容之前,你一定要关闭写入流。我相信,如果/当你这样做时,你会在读取文件时看到文件中的内容。

英文:

A couple of things:

  1. Object streams are very brittle and not ideal. Users of different versions of Java may not be able to open your HashMap in a version different from what it was serialized under. Instead, I recommend XML (already included in the JRE) or JSON (I beliee you need Jackson library... unless it has been added to the JRE)

  2. You don't need to buffer your input or output streams. To start with, buffered streams are for inefficient reading and writing (like reading by line, or writing (not all at once) to the File. But also Object streams and PrintWriter / PrintStream (which you are not using but I've included for completeness) already have buffering capacity baked in.

  3. You should definitely close your write stream before trying to read from the stream. I believe that if/when you do this, you'll see contents in the file when you read it

答案2

得分: 0

BufferedOutputStream具有内部缓冲区,大小为8192字节。除非数据超过缓冲区,或者您刷新整个数据,否则数据将保留在缓冲区中,因此不会写入文件。

似乎播放列表数据小于缓冲区大小 - 在写入完成后,您需要在out输出流上调用close()方法,或者使用try-with-resources方法。

英文:

BufferedOutputStream has internal buffers with size equal 8192 bytes. Until data will exceed the buffer or you flush it whole data is being kept in the buffer thus it won't be written to the file

Seems that playlist data is smaller than buffer size - you need to call close() method on your out output stream after writing is being finished or use try-with-resources approach

答案3

得分: 0

基本上,您想要序列化一个对象,具体而言是HashMap的一个实例,然后对其进行反序列化。

在Java中,序列化仅存储类成员的值。它使用实际的.class文件与.dat文件的组合来对对象进行反序列化。因此,如果您序列化一个空的HashMap.dat文件将几乎是空的。在您的情况下,它是空的,因为您在写入后没有关闭文件。

下面的代码是序列化和反序列化HashMap的最简示例。请注意,它使用try-with-resources来确保在使用后关闭.dat文件。它还使用multi-catch来处理异常。

代码之后有代码解释。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;

public class SongList {

    public static void main(String[] args) {
        File f = new File("songlist.dat");
        try (FileOutputStream fos = new FileOutputStream(f);
             ObjectOutputStream oos = new ObjectOutputStream(fos)) {
            HashMap<String, String> playList = new HashMap<>();
            oos.writeObject(playList);
        }
        catch (IOException xIo) {
            xIo.printStackTrace();
        }
        try (FileInputStream fis = new FileInputStream(f);
             ObjectInputStream ois = new ObjectInputStream(fis)) {
            HashMap<?, ?> playList = (HashMap<?, ?>) ois.readObject();
        }
        catch (IOException | ClassNotFoundException x) {
            x.printStackTrace();
        }
    }
}
  • 不需要BufferedOutputStreamBufferedInputStream
  • 在运行时,当您反序列化HashMap时,Java无法知道HashMap条目的类型是什么。这就是为什么您会收到警告。请注意,这是警告而不是错误。这就是我在读取.dat文件时使用?通配符的原因。
  • 由于您没有发布Song类的代码,我将HashMap的值类型更改为String,以保持简单。您可以在代码中继续使用Song
  • 创建新的FileOutputStream会创建一个新的空文件。为已经存在的文件创建新的FileOutputStream将删除文件内容。如果要追加到现有文件,请使用类FileOutputStream此构造函数

顺便说一下,不应该关闭包装标准输入的Scanner

英文:

Basically you want to serialize an object, specifically an instance of HashMap and then de-serialize it.

Serialization in java only stores the values of the class members. It uses a combination of the actual .class file together with the .dat file to de-serialize an object. Hence if you serialize an empty HashMap, the .dat file will be [almost] empty. In your case it is empty because you didn't close the file after writing it.

Below code is a minimal example of serializing and de-serializing a HashMap. Note that it uses try-with-resources to ensure that the .dat files are closed after use. It also uses multi-catch to handle exceptions.

Explanations of the code appear after it.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;

public class SongList {

    public static void main(String[] args) {
        File f = new File(&quot;songlist.dat&quot;);
        try (FileOutputStream fos = new FileOutputStream(f);
             ObjectOutputStream oos = new ObjectOutputStream(fos)) {
            HashMap&lt;String, String&gt; playList = new HashMap&lt;&gt;();
            oos.writeObject(playList);
        }
        catch (IOException xIo) {
            xIo.printStackTrace();
        }
        try (FileInputStream fis = new FileInputStream(f);
             ObjectInputStream ois = new ObjectInputStream(fis)) {
            HashMap&lt;?, ?&gt; playList = (HashMap&lt;?, ?&gt;) ois.readObject();
        }
        catch (IOException | ClassNotFoundException x) {
            x.printStackTrace();
        }
    }
}
  • BufferedOutputStream and BufferedInputStream are not required.
  • At runtime, when you de-serialize the HashMap, java has no way of knowing what the types are for the entries in the HashMap. That's why you are getting the warning. Note that it is a warning and not an error. That's why I use the ? wildcard when reading the .dat file.
  • Since you didn't post the code of class Song, I changed the HashMap value type to String so as to keep things simple. You can continue to use Song in your code.
  • Creating a new FileOutputStream creates a new, empty file. Creating a new FileOutputStream for a file that already exists will remove the file contents. If you want to append to an existing file, use this constructor of class FileOutputStream.

By the way, you should not close a Scanner that wraps standard input.

huangapple
  • 本文由 发表于 2020年9月12日 04:49:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/63854145.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定