我正在尝试编写两个程序,一个程序写入文本文件,另一个程序读取文本文件。我尝试过使用 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 对象,删除最后一个“new” line”来自 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 程序,它也无法正确读取。这里可能出现什么问题?
编辑:稍微调整一下缓冲区大小后,我意识到文件读取错误,因为缓冲区大小小于文件中的内容。这可能与文件编码有关吗?
最佳答案
我发现问题所在了。
首先,在writer程序中,我需要在打开文件 channel 后添加fileChannel.truncate(0);
。这样,我会删除文件的旧内容并从头开始写入。如果没有该行,我将在写入时用新内容覆盖文件的旧内容,如果新内容比旧内容短,则旧内容仍将保留在新内容未覆盖的位置。只有当我确定新内容至少与旧内容一样大并且会完全重写它时,我才不需要截断选项,但对我来说情况并非如此。
其次,对于阅读器来说,它没有读取整个文件的原因是因为 while 循环将在文件内容的最后一部分附加到 StringBuilder 之前结束。我修改了代码并稍微更改了操作顺序后,如下所示:
numOfBytesRead = 0;
while (numOfBytesRead != -1) {
numOfBytesRead = fileChannel.read(buffer);
buffer.flip();
readObjects.append(new String(buffer.array()));
buffer.clear();
}
它运行没有问题。
关于java - 同时使用 java.nio.FileChannel 从两个不同的 JVM 写入和读取文本文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57760284/