Java InputStream读取方法为NFS安装位置中的文件返回ASCII"NUL"字符

gre*_*ryp 4 java io nfs file tail

我有一个Java进程,它使用Java RandomAccessFile读取给定文件,并根据文件内容进行一些处理.此文件是一个日志文件,由另一个java进程更新.读取该文件的java进程位于另一台计算机上,并具有NFS挂载设置以访问远程服务器中的文件.基本上,读取文件的进程将根据RandomAccessFile的文件长度和位置轮询文件中的更改,并为遇到的每个字节调用处理程序方法.问题是我有时会从RandomAccessFile读取方法返回ASCII'NUL'字符

int charInt = read();
Run Code Online (Sandbox Code Playgroud)

也就是说,charInt在某些情况下返回0,并在一段时间后返回有效字符.但后来我错过了流中的人物正在阅读NULs

我尝试使用http://commons.apache.org/io/apidocs/org/apache/commons/io/input/Tailer.html,我收到了每行的通知.但是在这些行中我有时会注意到ASCII NUL字符.我已经通过unix/linux的Java IO实现中的跟踪"tail -f" - 我的java进程类似,但后来我开始认为问题在于NFS挂载或者一些bug的java IO在尝试读取时来自NFS安装.我从普通文件(不在NFS挂载中)执行了一些测试读取,并且有一个连续写入它的进程.所有这些测试都是成功的.我也试过java BufferedReader,因为文件流实际上是一个字符流,即使我可以把它当作字节流.我仍然得到NUL角色.

不确定这是否重要 - NFS挂载是一个只读(ro).感谢任何帮助.谢谢.

我也尝试了以下内容:

FileWriter fileWriter;
    try {
        fileWriter = new FileWriter("<OUT_FILE>", true);
    } catch (IOException e) {
        throw new RuntimeException("Exception while creating file to write sent messages ", e);
    }
    BufferedWriter bufWriter = new BufferedWriter(fileWriter);

    Runtime r = Runtime.getRuntime();
    Process p = r.exec("tail -f <PATH_TO_IN_FILE>");
    Scanner s = new Scanner(p.getInputStream());
    while (s.hasNextLine()) {     
        String line = s.nextLine(); 
        bufWriter.write(line);
        bufWriter.write(System.getProperty("line.separator"));
        bufWriter.flush();

    }
    bufWriter.close();                               
Run Code Online (Sandbox Code Playgroud)

而且我仍然得到NUL角色.在这里,我将我读取的行写入文件,然后我可以比较IN文件和OUT文件.我看到一个场景线被跳过(有NUL字符).所有其他线路比较好 - 所以从大约13000线,我们看到大约100线不匹配.另外一个奇怪的事情是我跑得少了,我也可以看到这里的NUL角色,基本上还有^ C ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @的形式^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @ ^ @然后是有效行.还有一件事我注意到在错过行的过程中,文件在写入过程中得到了很快的更新,所以基本上xml消息被写入文件20110729 13:44:06.070097然后下一个文件被写入20110729 13 :44:06.100007.从第二个xml消息中错过了行.更多发现:我们正在读取文件的文件路径是在共享NAS中.

Gre*_*ale 7

我意识到这个问题现在已经超过一年了,但我会在其中添加我所知道的内容,以防其他人遇到这个问题时遇到这个问题.

此问题中描述的NUL字符由于对正在读取的文件的异步写入而出现.更具体地说,来自远程文件写入器的数据包已经无序到达,并且NAS缓冲区已经提交了稍后的数据包并用NUL字符填充该区域以用于未接收的数据.当收到丢失的数据包时,NAS缓冲区会提交它,覆盖那些空字符.

在我们第一次遇到这个的应用程序中,我们逐行读取文件,并跟踪成功读取的最后一个行号(因此我们可以随时停止并在我们停止的地方再次启动).我们处理此问题的临时解决方案只是在每次读取时专门检查"\ 0",并在遇到时关闭文件,等待1秒钟并重新打开文件,排队到我们停止的位置.通常,当我们再次读取该行时,实际文本已被提交.

虽然关闭并重新打开文件可能看起来很戏剧性,但在不这样做的情况下进行恢复是有问题的.您无法标记/重置BufferedReader来解决它,因为一旦将字符读入读取器的缓冲区,它们将不会从文件中重新读取,只有在您每次尝试再次读取时才会反刍.

获取底层的FileChannel,并读取和设置position()也会失败,因为您在文件中的位置包含读入缓冲区的字符,您可能还没有看到过,并且最终会跳过那些看不见的数据.

我们正在测试一个解决方案,我们扩展了InputStreamReader类并覆盖了read(char [],int,int)方法,使用filechannel在每次读取之前获取位置,调用超类的read方法,检查\ 0并重置如果找到filechannel位置,则返回0作为读取的字符数.