gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-11-01 01:56:56 24 4
gpt4 key购买 nike

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

int charInt = read();

也就是说,charInt 在某些情况下返回 0,并在一段时间后返回有效字符。但是后来我在流读取 NULs 期间丢失了字符

我尝试使用 http://commons.apache.org/io/apidocs/org/apache/commons/io/input/Tailer.html我在哪里收到每一行的通知。但是在这些行中,我有时会注意到 ASCII NUL 字符。我也在 Java IO implementation of unix/linux "tail -f" 中进行了追踪 - 我的 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();

但我仍然得到 NUL 字符。在这里,我将读取的行写入文件,以便我可以比较 IN 文件和 OUT 文件。我看到有一次跳过了行(带有 NUL 字符)。所有其他行都比较好 - 所以从大约 13000 行中,我们看到大约 100 行不匹配。另外一件奇怪的事情是我跑得少了,我也可以在这里看到 NUL 字符,基本上是 ^C^@^@^@^@^@^@^@^@^@ 的形式^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^@^@^@^@^@然后是有效行。在错过这些行的时候我注意到的另一件事是,文件在写入过程中更新得非常快,所以基本上一条 xml 消息在 20110729 13:44:06.070097 写入文件,然后在 20110729 13 写入下一条消息:44:06.100007。第二个 xml 消息中缺少行。更多发现:我们正在读取文件的文件路径位于共享 NAS 中。

最佳答案

我意识到这个问题现在已有一年多了,但我会添加我所知道的,以防其他有这个问题的人像我一样偶然发现它。

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

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

虽然关闭并重新打开文件看起来很戏剧化,但不这样做就无法恢复。您不能标记/重置 BufferedReader 来解决它,因为一旦字符被读入读取器的缓冲区,它们将不会从文件中重新读取,只会在您每次尝试再次读取时反省。

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

我们正在测试一个解决方案,我们扩展了 InputStreamReader 类并覆盖了 read(char[], int, int) 方法以使用文件 channel 在每次读取之前获取位置,调用父类(super class)的 read 方法,检查\0 并在找到时重置文件 channel 位置,返回 0 作为读取的字符数。

关于Java InputStream 读取方法为 NFS 安装位置中的文件返回 ASCII 'NUL' 字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6814404/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com