Java 返回ASCII';NUL';NFS装载位置中文件的字符
我有一个Java进程,它使用Java RandomAccessFile读取给定的文件,并根据文件内容进行一些处理。该文件是一个日志文件,由另一个java进程更新。读取文件的java进程位于另一台计算机上,并且具有NFS装载设置以访问远程服务器中的文件。基本上,读取文件的进程将根据RandomAccessFile的文件长度和位置轮询文件中的更改,并为遇到的每个字节调用处理程序方法。问题是,我有时会从RandomAccessFile读取方法返回ASCII“NUL”字符Java 返回ASCII';NUL';NFS装载位置中文件的字符,java,file,io,nfs,tail,Java,File,Io,Nfs,Tail,我有一个Java进程,它使用Java RandomAccessFile读取给定的文件,并根据文件内容进行一些处理。该文件是一个日志文件,由另一个java进程更新。读取文件的java进程位于另一台计算机上,并且具有NFS装载设置以访问远程服务器中的文件。基本上,读取文件的进程将根据RandomAccessFile的文件长度和位置轮询文件中的更改,并为遇到的每个字节调用处理程序方法。问题是,我有时会从RandomAccessFile读取方法返回ASCII“NUL”字符 int charInt = r
int charInt = read();
也就是说,charInt在某些情况下返回0,并且在一段时间后返回有效字符。但是,在流以NULs读取期间,我丢失了字符
我试着在收到每一行通知的地方使用。但在这些行中,我有时会注意到ASCII NUL字符。
我也曾在伦敦走过这条小路
-我的java过程与此类似,但我开始认为问题在于NFS挂载或尝试从NFS挂载读取时出现的一些错误java IO。我执行了一些测试,从一个普通文件(不在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();
FileWriter文件编写器;
试一试{
fileWriter=新的fileWriter(“,true);
}捕获(IOE异常){
抛出新的RuntimeException(“创建文件以写入已发送消息时出现异常”,e);
}
BufferedWriter bufWriter=新的BufferedWriter(fileWriter);
Runtime r=Runtime.getRuntime();
进程p=r.exec(“tail-f”);
扫描器s=新扫描器(p.getInputStream());
而(s.hasNextLine()){
字符串行=s.nextLine();
bufWriter.write(行);
写入(System.getProperty(“line.separator”);
bufWriter.flush();
}
bufWriter.close();
但我还是得到了NUL字符。在这里,我将读取的行写入一个文件,这样我就可以比较IN文件和OUT文件。我看到有一次跳过了行(使用NUL字符)。所有其他行都比较好-因此从大约13000行中,我们看到大约100行中存在不匹配。另一件奇怪的事情是,我的跑步次数少了,我可以看到NUL字符,基本上是^C的形式^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
然后是有效行。还有一件事我注意到,在这些行丢失的过程中,文件在写入过程中更新得非常快,因此基本上是在20110729 13:44:06.070097向文件写入一条xml消息,然后在20110729 13:44:06.100007向文件写入下一条消息。第二条xml消息中的行丢失。更多发现:我们读取文件的文件路径位于共享NAS中 您是否尝试过这样的方法:
BufferedReader input = new BufferedReader(new FileReader(args[0]));
String currentLine = null;
while (true) {
if ((currentLine = input.readLine()) != null) {
System.out.println(currentLine);
continue;
}
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
如果无法从文件中读取任何内容,则currentLine将为空
我怀疑是否存在特定的NFS+Java问题,您通过NFS访问文件的事实对VM来说应该是未知的。我意识到这个问题已经存在一年多了,但我会补充我所知道的,以防其他有此问题的人像我一样偶然发现它 此问题中描述的NUL字符是由于异步写入要读取的文件而出现的。更具体地说,来自远程文件编写器的数据包已无序到达,NAS缓冲区已提交一个稍后的数据包,并用NUL字符填充未接收数据的区域。当收到丢失的数据包时,NAS缓冲区会提交该数据包,覆盖这些空字符 在我们第一次遇到这种情况的应用程序中,我们逐行读取一个文件,并跟踪成功读取的最后一个行号(因此,我们可以随时停止,并在停止的地方重新启动)。我们处理此问题的临时解决方案只是在每次读取时专门检查“\0”,当遇到此问题时,关闭文件,等待1秒,然后重新打开文件,排队等待到我们停止的位置。通常,当我们再次阅读该行时,实际文本已经提交 虽然关闭和重新打开文件看起来很戏剧性,但不这样做进行恢复是有问题的。您无法标记/重置BufferedReader来解析它,因为一旦将字符读入读卡器的缓冲区,它们就不会从文件中重新读取,只会在每次尝试再次读取时重复读取 获取底层FileChannel,读取和设置position()也会失败,因为文件中的位置包含了读到缓冲区中的字符,而您可能还没有看到这些字符,并且最终会跳过那些看不见的数据
我们正在测试一个解决方案,我们扩展了InputStreamReader类并覆盖了read(char[],int,int)方法,以使用filechannel在每次读取之前获取位置,调用超类的read方法,检查\0并重置filechannel位置(如果找到),返回0作为读取的字符数。谢谢。是的,我已经试过了——问题是在某些情况下,当我希望有有效字符时,我会在打印出来的行中得到NUL字符。此外,有时返回的行越来越大,因为流无法读取LF或CR字符,而是读取NUL字符