Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java newOutputStream(路径、新建、关闭时删除)不写入文件_Java_Nio - Fatal编程技术网

Java newOutputStream(路径、新建、关闭时删除)不写入文件

Java newOutputStream(路径、新建、关闭时删除)不写入文件,java,nio,Java,Nio,我有以下代码: import java.io.IOException; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Paths; import static java.nio.file.StandardOpenOption.CREATE_NEW; import static java.nio.file.StandardOpenOption.DELETE_ON_CLOSE; publ

我有以下代码:

import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;

import static java.nio.file.StandardOpenOption.CREATE_NEW;
import static java.nio.file.StandardOpenOption.DELETE_ON_CLOSE;

public class Test {
    public static void main(String[] args) throws IOException {
        try (OutputStream outputStream = Files.newOutputStream(Paths.get("test"), CREATE_NEW, DELETE_ON_CLOSE)) {
            outputStream.write(123);
            outputStream.flush();
            System.out.println("done");
        }
    }
}

我在调用
System.out.println
时设置了一个断点,并检查了我的工作目录。没有名为
test
的文件。为什么输出流不写入文件

原因是,在Linux上,即使文件处于打开状态,您也可以从目录中删除文件(此处假定有适当的权限)。在Windows下,这是不可能的

源于

//如果关闭时删除,请立即取消文件链接。规范明确指出
//当
//打开后被攻击者替换。
if(flags.deleteOnClose){

如果您将代码修改为

for (int i = 0; i < 10; i++) {
    outputStream.write(123);
    outputStream.flush();
    System.out.println("flush...");
    Thread.sleep(10_000);
}
编辑如果您只想确保在应用程序退出时删除临时文件,请查看下面的代码段

import java.io.File;
import java.io.OutputStream;
import java.nio.file.Files;
import static java.nio.file.StandardOpenOption.CREATE_NEW;
public class Main {
    public static void main(String[] args) throws Exception {
        File file = new File("/tmp/test");
        file.deleteOnExit();
        System.out.println("tempFile = " + tempFile);
        try (OutputStream outputStream = Files.newOutputStream(file.toPath(),
                CREATE_NEW)) {
            outputStream.write(123);
            outputStream.flush();
            System.out.println("done");
        }
        System.out.printf("%s exists: %s%n", file, file.exists());
    }
}
应用程序完成时,将删除文件
/tmp/test

输出(此时文件仍然存在)

如果您现在在控制台上检查

$ ls /tmp/test
ls: cannot access '/tmp/test': No such file or directory
在你甚至不关心文件名的情况下,你可以考虑使用一个随机生成的文件。
File tempFile = File.createTempFile("foo_", ".tmp", new File("/tmp"));
编辑可以使用另一种解决方案

  • 创建文件(首选使用随机临时文件名)
  • 打开一个
    InputStream
  • DELETE\u ON\u CLOSE打开
    OutputStream
  • 按那个顺序做,它会像你期望的那样工作

    在下面找到一个工作片段

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import static java.nio.charset.StandardCharsets.UTF_8;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import static java.nio.file.StandardOpenOption.APPEND;
    import static java.nio.file.StandardOpenOption.DELETE_ON_CLOSE;
    import static java.nio.file.StandardOpenOption.READ;
    
    public class DeleteOnClose {
    
        public static void main(String[] args) throws IOException {
            Path path = Paths.get("/tmp/test");
            System.out.println("before create: " + Files.exists(path));
            Files.createFile(path);
            System.out.println("after create: " + Files.exists(path));
            try (InputStream in = Files.newInputStream(path, READ);
                    OutputStream out = Files.newOutputStream(path, APPEND, 
                            DELETE_ON_CLOSE)) {
                out.write("Hello file!".getBytes(UTF_8));
                out.flush();
    
                for (int c = in.read(); c >= 0; c = in.read()) {
                    System.out.print((char) c);
                }
                System.out.println();
            }
            System.out.println("after close: " + Files.exists(path));
        }
    }
    
    输出

    before create: false
    after create: true
    Hello file!
    after close: false
    

    嗯…对我有用(使用
    线程。睡眠
    而不是断点)。你运行的是什么操作系统?OSX。如果我删除
    DELETE\u on\u CLOSE
    ,它对我也有效。我想发生的是基于Unix的操作系统会立即删除该文件,因为仍然可以访问带有打开文件句柄的删除文件。这似乎违反了API。是的,确实如此-我将在Linux上尝试,看看是否可以重新访问oduce(顺便说一句,如果你提供一个完整的应用程序,包括导入,人们会更容易复制它。)我在Linux上也经历过同样的行为,@Max-
    DELETE_on_CLOSE
    文档确实说明了“关于何时和如何删除文件的许多细节是特定于实现的,因此没有指定。”
    deleteOnExit
    对我不起作用,因为这是一个长期运行的流程(服务)。使用
    deleteOnExit
    可能会导致在JVM存在之前磁盘已满。@Max您能否提供有关如何使用此文件的详细信息。由于当前您仅创建一个
    只写
    文件,以便在关闭时删除。在当前情况下,这似乎没有任何意义。是否有其他进程/任务读取该文件?请您提供一个代码片段,说明您希望如何读取该文件。当然。我正在接受一个文件作为rest服务中的上载。我最终会将该文件作为流传递给另一个服务,但我需要首先评估上载文件的内容。鉴于该文件相当大,我不想将其全部存储在内存中。对吗现在我正在删除
    最后
    块中的文件。这很好,看起来
    DELETE\u ON\u CLOSE
    会更合适,但显然不是。@Max看看新添加的示例。它与
    DELETE\u ON\u CLOSE
    选项一起工作。有趣的想法!谢谢。
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import static java.nio.charset.StandardCharsets.UTF_8;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import static java.nio.file.StandardOpenOption.APPEND;
    import static java.nio.file.StandardOpenOption.DELETE_ON_CLOSE;
    import static java.nio.file.StandardOpenOption.READ;
    
    public class DeleteOnClose {
    
        public static void main(String[] args) throws IOException {
            Path path = Paths.get("/tmp/test");
            System.out.println("before create: " + Files.exists(path));
            Files.createFile(path);
            System.out.println("after create: " + Files.exists(path));
            try (InputStream in = Files.newInputStream(path, READ);
                    OutputStream out = Files.newOutputStream(path, APPEND, 
                            DELETE_ON_CLOSE)) {
                out.write("Hello file!".getBytes(UTF_8));
                out.flush();
    
                for (int c = in.read(); c >= 0; c = in.read()) {
                    System.out.print((char) c);
                }
                System.out.println();
            }
            System.out.println("after close: " + Files.exists(path));
        }
    }
    
    before create: false
    after create: true
    Hello file!
    after close: false