在写入器关闭后,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.getInputS­tream()));
        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#客户端读取它并在之后立即更改它?

在写入器关闭后,Java继续使用文件

首先:你想要完成什么?你做的事看起来很不寻常。

第二个:让我给你一个答案。我似乎在很多很多年前就遇到过这个问题。当时它运行在某种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()