在写入器关闭后,Java继续使用文件
本文关键字:继续 Java 文件 | 更新日期: 2023-09-27 18:13:33
刚刚编写了一个java程序,将一些内容写入从手机接收的文件中,文件被写入,我想使用c#客户端读取该文件,但当试图读取文件时,我得到错误:文件正在被另一个进程使用,即使我确保我关闭了文件写入器…
这是服务器的java代码:import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.File;
import java.net.InetAddress;
public class VRSC {
public static void main(String[] args) throws IOException {
String username = System.getProperty("user.name");
InetAddress ip = InetAddress.getLocalHost();
File file = new File("C:/Users/"+username+"/Desktop/VRemote.cmd");
Socket clientSocket = null;
ServerSocket serverSocket = null;
if (!file.exists()) {
file.createNewFile();
}
try{
serverSocket = new ServerSocket(5665);
System.out.println("server started on port 5665");
System.out.println("Please connect to: " + ip.getHostAddress());
System.out.println("Waiting...");
clientSocket = serverSocket.accept();
}catch(Exception e){} //read & display the message
//BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
Scanner in1 = new Scanner(clientSocket.getInputStream());
String mes;
while(true){
if (in1.hasNext())
{ FileWriter fw = new FileWriter(file.getAbsoluteFile());
mes=in1.nextLine();
System.out.println("Command Received: "+mes);
fw.write("VCommand: " + mes);
fw.flush();
fw.close();
}
}
}
}
有没有人知道我如何让服务器写入文件,但允许c#客户端读取它并在之后立即更改它?
首先:你想要完成什么?你做的事看起来很不寻常。
第二个:让我给你一个答案。我似乎在很多很多年前就遇到过这个问题。当时它运行在某种Windows操作系统上。事实证明,close()
操作只会通知操作系统终止对该文件的任何未来操作,但仅此而已。操作系统将做一些内部清理作为响应,但如果当前机器上发生了一些I/O,则可能会延迟此清理。因此,不能指望每次调用close()
时文件都被关闭。这将导致您注意到的结果:当其他进程试图读取文件时,您可能会遇到错误。所以这不是Java的问题,这是Windows操作系统的普遍问题。(当然,对于其他操作系统,您可能会遇到类似的问题:这是关于内部异步操作系统任务的一般问题。)
我找到的唯一解决方案是给Windows操作系统一些时间来真正关闭文件。据我所知,即使在繁重的I/O负载下,5秒的延迟也足够了。因此,在c#程序中执行以下操作:
- 启动c#进程并通知它新文件
- 让这个c#进程休眠5秒
- 运行循环:
- 尝试打开 文件
- 成功后:按照计划进行并使用数据执行任务
- 错误:休眠1秒并重复循环
(当然这个解决方案只适用于文件i/O通常阻塞文件的Windows。)
如果你有更好的解决方案,我很有兴趣看看。这是我们实施的解决方案,它运行得非常好。
在Windows上写文件通常会阻止其他进程读取同一文件。通过深入研究Java I/O,在Java中可能有办法解决这个问题。但与上述解决方案的简单性相比,它通常不值得付出努力。因此,如果您确实不需要选择不同的解决方案,请考虑实现我在这里介绍的解决方案。
在catch内的循环中,检查in1
是否有可用的单词。然后等着排满队。如果您收到一个单词(带有结束空格),但没有endoline字符,该怎么办?java线程将在打开FileWriter的情况下等待nextLine()
。
=>尝试在nextLine()
调用之后创建FW
,或者使用hasNextLine()
代替hasNext()
另外,如注释中所述,始终在finally块中调用close()
。