2013-03-04 83 views
3

每隔5秒(例如),服务器会检查文件是否已添加到特定目录。如果是,它会读取并处理它们。有关文件可能相当大(例如100多莫),因此将它们复制/上传到上述目录可能会很长。读取尚未完成复制/上传的文件内容

如果服务器试图访问尚未完成复制/上传的文件,该怎么办? JAVA如何管理这些并发访问?它依赖于服务器的操作系统吗?


我作了尝试,复制从远程服务器〜1300000线TXT文件(即约200 Mo)的我的本地计算机:它需要大约5秒。在这个失误,我运行下面的Java类:

public static void main(String[] args) throws Exception { 

    String local = "C:\\large.txt"; 

    BufferedReader reader = new BufferedReader(new FileReader(local)); 
    int lines = 0; 
    while (reader.readLine() != null) 
     lines++; 
    reader.close(); 

    System.out.println(lines + " lines"); 

} 

我得到以下异常:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
    at java.util.Arrays.copyOf(Arrays.java:2882) 
    at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:100) 
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:515) 
    at java.lang.StringBuffer.append(StringBuffer.java:306) 
    at java.io.BufferedReader.readLine(BufferedReader.java:345) 
    at java.io.BufferedReader.readLine(BufferedReader.java:362) 
    at main.Main.main(Main.java:15) 

当运行类,一旦文件完成被复制,我得到的预期输出(即1229761 lines),所以这个例外不是由于文件的大小(正如我们首先想到的那样)。 JAVA在后台做什么,抛出了这个异常呢?

+0

您是否尝试过使用大量的Xmx来确保它不是真正的OOME? – assylias 2013-03-04 11:34:26

+0

我的猜测是,readLine()在某种程度上实际上没有找到换行符(可能是因为换行符由于某种原因,不同的O.S.或某种编码问题而不同),并且一次读取非常大的行。 – ddmps 2013-03-04 11:40:05

+0

@assylias我试着用最大1 Gb的JAVA堆大小(即'-Xmx1024m')尝试,但仍然抛出异常。 – sp00m 2013-03-04 13:18:24

回答

1

JAVA如何管理这些并发访问?它依赖于服务器的操作系统吗?

这取决于特定的操作系统。如果您在单个JVM中运行副本和服务器,则可能会有很大的帮助。但是,如果客户端和服务器由不同的JVM代表(甚至更多,在不同的机器上启动),它们都变成了特定平台。

JavaDoc for AsynchronousFileChannel:

与FileChannel,通过这个类的一个实例提供的文件的视图被保证是与由其他实例在同一程序中提供的相同文件的其他观点的。然而,由这个类的实例提供的视图可能与可能与其他并发运行程序看到的视图一致,这是由于底层操作系统执行缓存以及网络文件系统协议引起的延迟。无论编写这些其他程序的语言如何,以及它们是在同一台机器上还是在其他某台机器上运行,情况都是如此。任何此类不一致的确切性质都与系统有关,因此未予指明。

1

为什么使用缓冲读取器来计算行数?

来自javadoc: 从字符输入流中读取文本,缓冲字符以提供字符,数组和行的有效读取。

这意味着它会“缓冲”,即。保存整个文件在内存中导致堆栈转储。尝试一个FileReader。

+0

这个问题不是关于读取行,而是访问这样的文件。我举了一个例子来说明我的问题。 – sp00m 2013-03-04 20:58:12

+1

我的答案实际上仍然正确。你想知道为什么你要得到一个OOME,这是因为你正在试图把一个巨大的文件放在内存中。这给你两个选择:1.不要把它放在内存中(正如我上面所建议的那样),或者2.按照其他人的建议,通过-Xmx标志增加内存量。 – JoeG 2013-03-06 12:23:29