我正在制作一个Java Web应用程序,它将在Tomcat下运行。代码将从文件(在服务器上)读取一个数字,进行一些处理,并将结果写回同一文件(覆盖旧内容,不附加它)并将其显示在用户的HTML页面中。
我正在使用这个单例(以避免可能的多线程问题)来读取和写入文件,以及返回数字。 servlet类调用此方法。
public class Singleton {
private static Singleton instance;
private ObjectOutputStream fileOut;
private ObjectInputStream fileIn;
private File file;
private static final String fileName = "/Users/Timmy/Desktop/IDFile.txt";
private static final int SCALE = 1000000;
public synchronized long getNewID() throws IOException{
if(file == null){
file = new File(fileName);
}
if(!file.exists()){
file.createNewFile();
}
fileOut = new ObjectOutputStream(new FileOutputStream(file));
fileIn = new ObjectInputStream(new FileInputStream(file));
long lastId;
String idString;
try{
idString = fileIn.readUTF();
lastId = Long.parseLong(idString);
}catch(EOFException e){
System.out.println("EOF EXCEPTION WHILE READING");
e.printStackTrace();
lastId = (long)(Math.random() * SCALE);
}
fileIn.close();
fileIn = null;
long nextId = lastId + ((long)(Math.random() * SCALE)) + 1;
fileOut.writeChars(Long.toString(nextId) + "\n");
fileOut.close();
fileOut = null;
return nextId;
}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
这是Stack Trace:
java.io.EOFException
at java.io.DataInputStream.readUnsignedShort(DataInputStream.java:340)
at java.io.ObjectInputStream$BlockDataInputStream.readUnsignedShort(ObjectInputStream.java:2808)
at java.io.ObjectInputStream$BlockDataInputStream.readUTF(ObjectInputStream.java:2864)
at java.io.ObjectInputStream.readUTF(ObjectInputStream.java:1072)
at com.digitalpyrite.assassin.server.Singleton.getNewID(Singleton.java:37)
at com.digitalpyrite.assassin.server.Main.doGet(Main.java:42)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
我遇到的问题是每次调用getNewID()方法时,在读取文件时都会抛出EOFException。它应该仅在程序第一次运行时抛出,此时文件是新创建的并且为空。我尝试了各种不同的方法来读取这个文件,但都失败了。扫描程序抛出NoSuchElementException,Reader在读取文本时返回null等。我做错了什么?
答案 0 :(得分:0)
首先,在评论之外:此字符串"/Users/Timmy/Desktop/IDFile.txt"
看起来非常容易出错。在你的情况下可能不是问题,但你仍然应该对其进行非硬编码 - 就像这样,这是一个潜在的错误。
关于EOF问题:首先,FileInputStream
和FileOutputStream
与同一个File
对象互动。由于您没有交错使用它们,因此您应该在使用OutputStream
时将InputStream
的开头移至:
...
fileIn.close();
fileIn = null;
fileOut = new ObjectOutputStream(new FileOutputStream(file));
...
第二:你正在使用不同的编码进行写作。您应该使用writeUTF()
才能阅读readUTF()
:
idString = fileIn.readUTF();
...
fileOut.writeUTF(Long.toString(nextId) + "\n");
如果您选择这样做,请删除"\n"
换行符,否则Long.parseLong()
将 正确解析输入字符串。最好只使用.readLong()
和.writeLong()
(因为您无论如何都要使用OIS / OOS);那样你就可以避免处理字符串了:
lastId = fileIn.readLong();
...
fileOut.writeLong(nextId);