0

当 line clanovi = ((HashMap) in.readObject()); 时出现 EOF 异常 from 方法 load() 执行,但并非总是如此。它发生在 5-6 次之后,有时甚至是 10 次来自我的 servlet 的 load 方法调用,完全随机。请帮助我,我需要为明天早上的项目辩护解决这个问题:(

只是说 ClanPostave 是可序列化的。我尝试将 flush() 添加到加载方法中,但没有任何帮助。

public class Clanovi implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = 1L;


HashMap<String, ClanPostave> clanovi = new HashMap<String, ClanPostave>();

public HashMap<String, ClanPostave> getClanovi() {
    return clanovi;
}

public void setClanovi(HashMap<String, ClanPostave> clanovi) {
    this.clanovi = clanovi;
}


public synchronized void save(String path){

    try {

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(path + "/clanovi.dat"));
        out.writeObject(clanovi);
        out.close();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

@SuppressWarnings("unchecked")
public synchronized void load(String path){

    try {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(path + "/clanovi.dat"));
        clanovi = ((HashMap<String,ClanPostave>) in.readObject());
        in.close();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

堆栈跟踪:

java.io.EOFException
    at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
    at java.io.ObjectInputStream.readClassDesc(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
    at java.io.ObjectInputStream.defaultReadObject(Unknown Source)
    at java.util.Calendar.readObject(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor25.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeReadObject(Unknown Source)
    at java.io.ObjectInputStream.readSerialData(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
    at java.io.ObjectInputStream.readSerialData(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at java.util.HashMap.readObject(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor31.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeReadObject(Unknown Source)
    at java.io.ObjectInputStream.readSerialData(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at beans.Clanovi.load(Clanovi.java:52)
    at servlets.DodajClana.doPost(DodajClana.java:51)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Unknown Source)

由于 Joni,EOFException 消失了,但现在我遇到了这个问题:

try {
            clanovi1.dodajClana(new ClanPostave(idclana,ime,prezime,mesto,new GregorianCalendar(datumGodina, datumMesec, datumDan),biografija,uloga));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        clanovi1.save(path);
        clanovi1.load(path);
        HashMap<String, ClanPostave> clanovi = clanovi1.getClanovi();

这段代码之后 HashMap 为空。在 Joni 建议的这个更改之前,它填充了在该 try 块中添加的值。有什么问题?

这是整个 servlet:

 package servlets;

    import java.io.IOException;
    import java.util.Calendar;
    import java.util.GregorianCalendar;
    import java.util.HashMap;

    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import beans.ClanPostave;
    import beans.Clanovi;
    import beans.Korisnik;

    /**
     * Servlet implementation class DodajClana
     */
    public class DodajClana extends HttpServlet {
        private static final long serialVersionUID = 1L;



        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.getRequestDispatcher("index.jsp").forward(request, response);
        }
        /**
         * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
         */
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            ServletContext ctx = getServletContext();   
            Korisnik korisnik = (Korisnik) request.getSession().getAttribute("korisnik");

            if(korisnik != null && korisnik.getAdmin()){
            String path = ctx.getRealPath("");
            String idclana = request.getParameter("idclana");
            String ime = request.getParameter("ime");
            String prezime = request.getParameter("prezime");
            String mesto = request.getParameter("mesto");
            int datumGodina = Integer.parseInt(request.getParameter("datumGodina"));
            int datumMesec = Integer.parseInt(request.getParameter("datumMesec"))-1;
            int datumDan = Integer.parseInt(request.getParameter("datumDan"));
            String biografija = request.getParameter("biografija");
            String uloga = request.getParameter("uloga");

            System.out.println(idclana);

            Clanovi clanovi1 = new Clanovi();
            clanovi1.load(path);

            if(!isDateValid(datumGodina, datumMesec, datumDan)){
                System.out.println("ne valja datum");
                request.setAttribute("greska1", "Nevalidan datum!");
            }

            if(clanovi1.getClanovi().containsKey(idclana)){
                System.out.println("ne valja id");
                request.setAttribute("greska2", "Clan sa tim ID-jem vec postoji u bazi!");
            }

            if((!isDateValid(datumGodina, datumMesec, datumDan))||clanovi1.getClanovi().containsKey(idclana)){

                request.getRequestDispatcher("/WEB-INF/clanGreska.jsp").forward(request, response);
            }

            boolean test = !((!isDateValid(datumGodina, datumMesec, datumDan))||(clanovi1.getClanovi().containsKey(idclana)) || ((!isDateValid(datumGodina, datumMesec, datumDan))||clanovi1.getClanovi().containsKey(idclana)));
            System.out.println(test);
            if(test){

                try {
                    clanovi1.dodajClana(new ClanPostave(idclana,ime,prezime,mesto,new GregorianCalendar(datumGodina, datumMesec, datumDan),biografija,uloga));
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                clanovi1.save(path);
                try {
                    System.out.println(clanovi1.getClan(idclana));
                } catch (Exception e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }

                try {
                    System.out.println(clanovi1.getClan(idclana));
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                HashMap<String, ClanPostave> clanovi = clanovi1.getClanovi();
                ctx.setAttribute("clanovi", clanovi);       
                request.getRequestDispatcher("index.jsp");
            }

            }                   

            else request.getRequestDispatcher("index.jsp").forward(request, response);
        }


        public synchronized boolean isDateValid(int year, int month, int day) {  
            boolean valid = true;  
            Calendar calendar = new GregorianCalendar(year, month, day);  
            if (year != calendar.get(Calendar.YEAR)) {  
                valid = false;  
            }  
            else if (month != calendar.get(Calendar.MONTH)) {  
                valid = false;  
            }  
            else if (day != calendar.get(Calendar.DAY_OF_MONTH)) {  
                valid = false;  
            }  
            return valid;  
        }  



    }
4

2 回答 2

1

防止读取不完整文件的一种方法是写入临时文件,然后重命名它:

    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(path + "/clanovi.tmp"));
    out.writeObject(clanovi);
    out.close();
    new File(path + "/clanovi.tmp").renameTo(new File(path + "/clanovi.ovi"));

这意味着该load进程现在可能在第一次运行时找不到文件,或者可能读取旧数据。

于 2013-07-07T20:32:03.413 回答
-1

可能您可以使用同步块/函数来加载并保存到序列化文件。

就像是 -

 public enum Operation {
           LOAD,
           SAVE;      
 }

 synchronized void loadOrSave(String path, Operation operation) {
     if (operation == Operation.LOAD) {
         //do load here
     } else {
         //do save here
     }

 }
于 2013-07-07T21:05:48.527 回答