Java ObjectInputStream在读取包含对象的文件时引发EOFEException

Java ObjectInputStream在读取包含对象的文件时引发EOFEException,java,serialization,objectinputstream,eofexception,Java,Serialization,Objectinputstream,Eofexception,我正试图从文件中读取Treemap。我知道文件中序列化了一个TreeMap,我的问题是OIS在该文件上抛出了一个EOFEException public class FileDBMapApi { private FileOutputStream OutPutter; private FileInputStream Inputter; private ObjectInputStream InputStream; private ObjectOutputStream

我正试图从文件中读取
Treemap
。我知道文件中序列化了一个
TreeMap
,我的问题是OIS在该文件上抛出了一个
EOFEException

public class FileDBMapApi {

    private FileOutputStream OutPutter;
    private FileInputStream Inputter;
    private ObjectInputStream InputStream;
    private ObjectOutputStream OutputStream;
    private NavigableMap<Integer, Object> data;
    private File currentFile;
    private int autoIncrement;

    /**
     * @param dataFile is the file to use as a database
     */
    public FileDBMapApi(String dataFile) {
        String fullPath = "data/" + dataFile;
        currentFile = new File(fullPath);
    }

    // initialiserar databasen
    public void init() {
        // checkar om filen existerar och isåfall assignar inputter och outputter till filen
        System.out.println(currentFile.exists() && !currentFile.isDirectory());
        if (currentFile.exists() && !currentFile.isDirectory()) {
            try {
                OutPutter = new FileOutputStream(currentFile);
                OutPutter.flush();
                Inputter = new FileInputStream(currentFile);
                OutputStream = new ObjectOutputStream(OutPutter);
                OutputStream.flush();
                InputStream = new ObjectInputStream(Inputter);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            // annars så skapar den filen och assignar det istället
            try {
                boolean temp1 = currentFile.getParentFile().mkdirs();
                boolean temp2 = currentFile.createNewFile();
                if (temp2) {
                    OutPutter = new FileOutputStream(currentFile);
                    Inputter = new FileInputStream(currentFile);
                    OutputStream = new ObjectOutputStream(OutPutter);
                    InputStream = new ObjectInputStream(Inputter);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // läser in hashmapen från filen
        this.convertData();
    }

    public void write() {
        try {
            PrintWriter n = new PrintWriter(currentFile);
            n.close();
            OutputStream.writeObject(data);
            OutputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public int add(Object o) {
        int id = autoIncrement;
        data.put(autoIncrement, o);
        autoIncrement++;
        return id;
    }

    public Object get(int i) {
        return data.get(i);
    }

    public void close() {
        try {
            OutPutter.close();
            Inputter.close();
            InputStream.close();
            OutputStream.flush();
            OutputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // returnar data
    public NavigableMap<Integer, Object> getAll() {
        return data;
    }

    public long getFileSize() {
        return currentFile.length();
    }

    // tar data från en fil och sätter in det till en hashmap
    private void convertData() {
        try {
            if (InputStream.read() != -1) {
                data = (NavigableMap) InputStream.readObject();
            } else {
                data = new TreeMap<>();
                System.out.println(data);
            }
            if (!data.isEmpty()) autoIncrement = data.lastKey();
            else autoIncrement = 0;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void closeAndWrite() {
        write();
        close();
    }

}
公共类FileDBMapApi{
私有文件输出流输出器;
私有文件输入流输入器;
私有对象输入流输入流;
私有对象输出流输出流;
私有导航地图数据;
私有文件;
私有整数自动递增;
/**
*@param dataFile是用作数据库的文件
*/
公共文件DBMAPAPI(字符串数据文件){
字符串fullPath=“data/”+数据文件;
currentFile=新文件(完整路径);
}
//初始化器数据库
公共void init(){
//检查om文件出口och是否为分配输入och输出直到文件
System.out.println(currentFile.exists()&&!currentFile.isDirectory());
if(currentFile.exists()&&!currentFile.isDirectory()){
试一试{
OutPutter=新文件OutputStream(当前文件);
exputter.flush();
Inputer=新文件InputStream(当前文件);
OutputStream=新对象OutputStream(输出器);
OutputStream.flush();
InputStream=新对象InputStream(输入者);
}捕获(例外e){
e、 printStackTrace();
}
}否则{
//安纳尔斯·斯卡帕(annars såskapar den filen och assignar det istället)
试一试{
布尔值temp1=currentFile.getParentFile().mkdirs();
布尔值temp2=currentFile.createNewFile();
如果(临时2){
OutPutter=新文件OutputStream(当前文件);
Inputer=新文件InputStream(当前文件);
OutputStream=新对象OutputStream(输出器);
InputStream=新对象InputStream(输入者);
}
}捕获(例外e){
e、 printStackTrace();
}
}
//哈斯马潘·弗雷恩文件中的läser
这是convertData();
}
公共空写(){
试一试{
PrintWriter n=新的PrintWriter(当前文件);
n、 close();
OutputStream.writeObject(数据);
OutputStream.flush();
}捕获(例外e){
e、 printStackTrace();
}
}
公共整数添加(对象o){
int id=自动递增;
数据输入(自动递增,o);
自动增量++;
返回id;
}
公共对象get(int i){
返回数据。获取(i);
}
公众假期结束(){
试一试{
outputer.close();
input.close();
InputStream.close();
OutputStream.flush();
OutputStream.close();
}捕获(例外e){
e、 printStackTrace();
}
}
//返回数据
公共NavigableMap getAll(){
返回数据;
}
公共长getFileSize(){
返回currentFile.length();
}
//在hashmap之前,数据中的tar数据在fil-och-sätter中
私有数据(){
试一试{
如果(InputStream.read()!=-1){
数据=(NavigableMap)InputStream.readObject();
}否则{
数据=新树映射();
系统输出打印项次(数据);
}
如果(!data.isEmpty())autoIncrement=data.lastKey();
否则自动递增=0;
}捕获(例外e){
e、 printStackTrace();
}
}
public void closeAndWrite(){
write();
close();
}
}

引发异常的是
convertData(0
方法。我已经检查了有问题的文件,它确实包含一个序列化的
Treemap
,该树映射已使用
write()
方法和
close()序列化
方法。现在我的问题是,在存储或检索数据时,我哪里做错了?

我会找到错误所在,但实际上,您的代码毫无意义,需要彻底检查:

public class FileDBMapApi {

    private FileOutputStream OutPutter;
    private FileInputStream Inputter;
您不需要将
文件输入/输出流
单独作为数据成员。请删除

    // initialiserar databasen
    public void init() {
        // checkar om filen existerar och isåfall assignar inputter och outputter till filen
        System.out.println(currentFile.exists() && !currentFile.isDirectory());
        if (currentFile.exists() && !currentFile.isDirectory()) {
            try {
                OutPutter = new FileOutputStream(currentFile);
                OutPutter.flush();
                Inputter = new FileInputStream(currentFile);
                OutputStream = new ObjectOutputStream(OutPutter);
                OutputStream.flush();
                InputStream = new ObjectInputStream(Inputter);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            // annars så skapar den filen och assignar det istället
            try {
                boolean temp1 = currentFile.getParentFile().mkdirs();
                boolean temp2 = currentFile.createNewFile();
                if (temp2) {
                    OutPutter = new FileOutputStream(currentFile);
                    Inputter = new FileInputStream(currentFile);
                    OutputStream = new ObjectOutputStream(OutPutter);
                    InputStream = new ObjectInputStream(Inputter);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
您可以将所有复杂的双重对话简化为:

try {
    currentFile.getParentFile().mkdirs();
    OutputStream = new ObjectOutputStream(new FileOutputStream(currentFile));
    InputStream = new ObjectInputStream(new FileInputStream(currentFile));
} catch (IOException exc) {
    exc.printStackTrace();
}
…尽管如果
init()会更好
抛出了
IOException
,而不是在内部捕获和吸收它。您编写的所有复杂代码只完成了这一点。同时打开一个文件进行输出和输入真的没有意义,在某些平台(如Windows)上也不起作用。您需要重新考虑这一点

    public void write() {
        try {
            PrintWriter n = new PrintWriter(currentFile);
            n.close();
问题就在这里。
PrintWriter
未使用,因此应该删除它,但真正的问题是您刚刚截断了输出文件,这保证了通过
ObjectInputStream
读取时会产生
IOException
。删除

    public void close() {
        try {
            OutPutter.close();
            Inputter.close();
            InputStream.close();
            OutputStream.flush();
            OutputStream.close();
这完全是胡说八道。
flush()
before
close()
是冗余的,您只需要关闭
InputStream
OutputStream
。它们将为您关闭嵌套的流,即使它们没有关闭,关闭嵌套的输出流,然后尝试刷新和关闭外部输出流也是没有意义的

        } catch (Exception e) {
            e.printStackTrace();
        }
同样,该方法应该抛出
IOException
,而不是吸收它

    public long getFileSize() {
        return currentFile.length();
    }
这是毫无意义的。在某些操作系统(如Windows)上,在关闭文件之前,目录项不会更新,因此您可以在此处返回零。您不需要知道文件的当前长度

        try {
            if (InputStream.read() != -1) {
这没有任何意义。在这里,您读取了一个字节并将其丢弃。由于您没有写入任何额外的字节,这只会使您与流失去同步。请删除此项

                data = (NavigableMap) InputStream.readObject();
            } else {
                data = new TreeMap<>();
                System.out.println(data);
            }
请参见上面的重新抛出
IOExcept
        } catch (Exception e) {
            e.printStackTrace();
        }
    public void closeAndWrite() {