在读取包含对象的文件时,ObjectInputStream会抛出EOFexception

时间:2016-12-11 21:11:36

标签: java serialization objectinputstream eofexception

我试图从文件中读取Treemap。我知道文件中有TreeMap序列化,我的问题是OIS会在该文件上抛出EOFexception

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();
    }

}

抛出异常的是convertData(0方法。我检查了相关文件,它确实包含序列化的Treemap,它已使用write()方法和close()方法序列化。现在我的问题是我在存储或检索数据方面做错了什么?

1 个答案:

答案 0 :(得分:0)

我会找到错误的地方,但实际上你的代码没有任何意义,需要彻底审查:

public class FileDBMapApi {

    private FileOutputStream OutPutter;
    private FileInputStream Inputter;

您不需要单独FileInput/OutputStreams作为数据成员。删除。

    // 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未使用,因此应将其删除,但这里的真正问题是您刚刚截断了输出文件,当通过{{1}读取时,保证会生成IOException }。删除。

ObjectInputStream

这都是胡说八道。 public void close() { try { OutPutter.close(); Inputter.close(); InputStream.close(); OutputStream.flush(); OutputStream.close(); 之前的flush()是多余的,您只需要关闭close()InputStream。他们会为你关闭他们的嵌套流,即使他们不这样做,关闭嵌套输出流和然后尝试刷新并关闭外部输出流是没有意义的。

OutputStream

该方法再次抛出 } catch (Exception e) { e.printStackTrace(); } ,而不是吸收它。

IOException

这是毫无意义的。在某些操作系统(如Windows)上,在关闭文件之前,目录条目不会更新,因此您可以在此处返回零。您不应该知道文件的当前长度。

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

这没有任何意义。在这里,您已经读取了一个字节并将其丢弃。由于您没有写任何额外的字节,这只会使您与流不同步。删除它。

        try {
            if (InputStream.read() != -1) {

这个“别的”也没有任何意义。如果文件为空或者不包含任何其他对象,则抛出 data = (NavigableMap) InputStream.readObject(); } else { data = new TreeMap<>(); System.out.println(data); } ,并且您应该采取任何规避措施。事实上,你应该再次抛出各种EOFException,而不是毫无意义地替换空IOExceptions

TreeMap

见上文重新投掷 } catch (Exception e) { e.printStackTrace(); } 。不要写这样的代码。

IOException

如果您确实需要,则此方法应命名为 public void closeAndWrite() { ,而您不需要。{/ p>

  

我检查了相关文件,确实包含序列化的writeAndClose()

检查了怎么样?只有一种方法可以检查,这是通过调用Treemap