使用 java.nio.FileChannel 同时从两个不同的 JVM 写入和读取文本文件



我正在尝试编写两个程序,一个写入文本文件,另一个从中读取。我尝试使用 java.io,但遇到了并发问题。但是,当我切换到java.nio时,我遇到了更大的问题,可能与并发性无关,因为我在尝试读/写时将文件锁定在两个程序中,而是读取或写入文件的实际方式。

编写器程序代码(相关部分(:

Path filePath = Paths.get("map.txt");
FileChannel fileChannel;
ByteBuffer buffer;
StringBuilder existingObjects = new StringBuilder();
while (true) {
for (FlyingObject fo : airbornUnitsList) {
existingObjects.append(fo.toString() + System.lineSeparator());
}
if(existingObjects.length() > System.lineSeparator().length())
existingObjects.setLength(existingObjects.length() - System.lineSeparator().length());
buffer = ByteBuffer.wrap(existingObjects.toString().getBytes());
fileChannel = FileChannel.open(filePath, StandardOpenOption.READ, StandardOpenOption.WRITE);
fileChannel.lock();
fileChannel.write(buffer);
fileChannel.close();
existingObjects.delete(0, existingObjects.length());
sleep(100);
}

FlyingObject是一个包含一些字段的简单类和一个被覆盖的 toString(( 方法,airbornUnitsList 是这些对象的列表,所以我基本上是遍历列表,将 FlyingObject 对象附加到 StringBuilder 对象,从 StringBuilder 中删除最后一个"新行",将其放入缓冲区并写入文件。如您所见,我在写入文件之前锁定了文件,然后在之后解锁了它。

读取器程序代码(相关部分(:

Path filePath = Paths.get("map.txt");
FileChannel fileChannel;
ByteBuffer buffer;
StringBuilder readObjects = new StringBuilder();
while (true) {
fileChannel = FileChannel.open(filePath, StandardOpenOption.READ, StandardOpenOption.WRITE);
fileChannel.lock();
buffer = ByteBuffer.allocate(100);
numOfBytesRead = fileChannel.read(buffer);
while (numOfBytesRead != -1) {
buffer.flip();
readObjects.append(new String(buffer.array()));
buffer.clear();
numOfBytesRead = fileChannel.read(buffer);
}
fileChannel.close();
System.out.println(readObjects);
}

即使我在文件中手动写入几行,然后运行 Reader 程序,它也无法正确读取它。这里可能有什么问题?

编辑:在玩了一点缓冲区大小后,我意识到文件被错误地读取,因为缓冲区大小小于文件中的内容。这可能与文件编码有关吗?

我发现了问题所在。

首先,在编写器程序中,我需要在打开文件通道后添加fileChannel.truncate(0);。这样,我将删除文件的旧内容并从头开始编写。如果没有那行,我只会在编写时用新内容覆盖文件的旧内容,如果新内容比旧内容短,旧内容仍将保留在新内容未覆盖的位置。只有当我确定新内容至少与旧内容一样大并且会完全重写它时,我才不需要截断选项,但对我来说并非如此。

其次,关于阅读器,它没有读取整个文件的原因是,while 循环将在文件内容的最后一部分附加到StringBuilder之前结束。在我修改了代码并稍微更改了操作顺序之后,如下所示:

numOfBytesRead = 0;
while (numOfBytesRead != -1) {
numOfBytesRead = fileChannel.read(buffer);
buffer.flip();
readObjects.append(new String(buffer.array()));
buffer.clear();
}

它工作没有问题。

最新更新