java - Tomcat servlet 无法读取文件

标签 java file tomcat servlets

我正在制作一个 Java 网络应用程序,它将在 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;
}

}

这是堆栈跟踪:

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。它应该只在程序第一次运行时抛出,当文件是新创建的并且是空的时。我尝试了各种不同的方法来读取这个文件,但都失败了。 Scanner 抛出 NoSuchElementException,Reader 在读取文本时返回 null 等。我做错了什么?

最佳答案

首先,在评论之外:这个字符串 "/Users/Timmy/Desktop/IDFile.txt" 看起来极易出错。在您的情况下,这可能不是问题,但您仍然应该对其进行取消硬编码——就像这样,这是一个正在形成的潜在错误。


关于EOF问题:首先,FileInputStreamFileOutputStream与同一个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);

关于java - Tomcat servlet 无法读取文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24744264/

相关文章:

ios - 如何在ios上实现非全屏文件预览

jsf - 如何找到 JSF 页面的正确 URL?在 IntelliJ IDEA 中打开导致 404

eclipse - 从外部 jar 到 maven 的项目转换失败

java - 如何获取当前加载的fxml文件的名称?

java - Oracle EBS 种子 APi 调用 java.sql.SQLException : Non supported SQL92 token at position: 6

java - struts 中的两个按钮相互内联

java - 相对布局不覆盖屏幕的宽度

python - 使用 urllib2 将大型二进制文件流式传输到文件

java - Scanner.hasNext() 在正常运行时返回 false,但在调试时返回 true

tomcat - SEVERE : Exception springSecurityFilterChain. .. ClassCastException ... 无法转换 DelegatingFilterProxy