Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/377.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
写入ZIP文件的文件仅在运行时可用[Java]_Java_Path_Filesystems_Java 7_Nio - Fatal编程技术网

写入ZIP文件的文件仅在运行时可用[Java]

写入ZIP文件的文件仅在运行时可用[Java],java,path,filesystems,java-7,nio,Java,Path,Filesystems,Java 7,Nio,我在使用Java7的文件系统和文件API将二进制文件写入简单的ZIP存档时遇到了问题 执行写入操作时出现问题,该操作不会引发任何异常,文件不会写入ZIP存档,但在运行时可用(Files.exists(backup)返回true,并且可以使用Files.readAllBytes(backup)读取文件) 当程序关闭并重新启动时,该文件将不再可用 片段 此方法应创建任何路径的备份,无论文件系统提供程序是谁,仅在ZIP存档中的路径上“失败” /** * Creates backup of path

我在使用Java7的
文件系统
文件
API将二进制文件写入简单的ZIP存档时遇到了问题

执行写入操作时出现问题,该操作不会引发任何异常,文件不会写入ZIP存档,但在运行时可用(
Files.exists(backup)
返回true,并且可以使用
Files.readAllBytes(backup)
读取文件)

当程序关闭并重新启动时,该文件将不再可用

片段

此方法应创建任何路径的备份,无论文件系统提供程序是谁,仅在ZIP存档中的路径上“失败”

/**
 * Creates backup of path provided by 'file' parameter.
 *
 * @param file input file requiring backup creation
 * @return backup file
 * @throws java.io.IOException thrown in case of unsuccessful backup attempt
 */
public static Path createBackup(Path file) throws IOException {

    FileSystem fileSystem = file.getFileSystem();
    Path backup = fileSystem.getPath(file.toString() + ".BAK");

    return Files.write(backup, Files.readAllBytes(file));

}

public static void main(String... args) {
   try {

      Path f = FileSystems.newFileSystem(Paths.get("a.zip"), null).getPath("file.bin");

      Path backup = createBackup(f);

      System.out.println(Files.exists(backup)); // prints "true"
      System.out.println(new String(Files.readAllBytes(backup))); // prints its bytes
      System.out.println(backup.toString()); // prints "file.bin.BAK"
   } catch (IOException ex) {
      System.err.println(ex);
   }

}
但该文件在ZIP中并不实际存在

编辑: 我已经设法使它工作了,但有一个问题。下面的代码关闭文件系统,但写入正确。需要以某种方式“刷新”/“重新打开”文件系统

public static Path createBackup(Path file) throws IOException {

   try(FileSystem fileSystem = file.getFileSystem()) {

      Path backup = fileSystem.getPath(file.toString() + ".BAK");
      return Files.write(backup, Files.readAllBytes(file));

   }
}
当原始方法被保留并且在所有操作完成后手动关闭文件系统时,它会删除zip文件并保留类似于
zipfstmp***.tmp的内容,并抛出:

java.nio.file.FileAlreadyExistsException: zipfstmp2666831581340533856.tmp -> a.zip

当tmp文件重命名为“a.zip”时,它是一个有效的修改存档。

下面是一个简单的示例,其中所有逻辑都在main方法中

解决这一问题的关键在于使用URI明确说明要使用哪种文件系统提供程序。你可能想知道为什么是罐子而不是拉链。在Java中,jar文件实际上是zip文件,但具有不同的文件扩展名。因此java可以使用相同的机制访问zip文件

我尝试了二进制文件和文本文件,它似乎在我的Win10机器上工作。只需将zip文件的源目录(///e:/a.zip)更改为指向zip文件的位置。对我来说,文件.bin.BAK被写入eclipse项目目录的根目录中(您可能还希望在部署时更改它)

import java.io.IOException;
导入java.net.URI;
导入java.nio.file.FileSystems;
导入java.nio.file.Files;
导入java.nio.file.Path;
导入java.nio.file.path;
导入java.nio.file.StandardCopyOption;
导入java.util.HashMap;
导入java.util.Map;
公开课考试{
公共静态void main(字符串…参数){
//创建URI以将源定义为Zip文件。
//我使用jar是因为它本质上是一个zip文件。
Map env=new HashMap();
环境出售(“创建”、“真实”);
URI=URI.create(“jar:file:///e:/a.zip");
试一试{
//在zip和外部构建到源文件的路径。
Path pathInZipfile=FileSystems.newFileSystem(uri,env.getPath(“/file.bin”);
Path extPath=Path.get(“file.bin.BAK”);
//如果文件不存在,请创建它。
如果(!Files.exists(extPath))
createFile(extPath);
//把文件复制过来。
copy(pathInZipfile、extPath、,
StandardCopyOption.REPLACE_现有);
}//结束尝试
捕获(IOEX异常){
例如printStackTrace();
}//捕获物
}//端干管
}//末级

您应该在创建文件系统的调用者中使用try with resource语句关闭。根本不需要在
createBackup
方法中处理文件系统

public static Path createBackup(Path file) throws IOException {
    Path backup = file.resolveSibling(file.getFileName().toString()+".BAK");
    return Files.copy(file, backup, StandardCopyOption.REPLACE_EXISTING);
}
public static void main(String... args) {
    try(FileSystem fs = FileSystems.newFileSystem(Paths.get("a.zip"), null)) {
       Path f = fs.getPath("file.bin");
       Path backup = createBackup(f);

       System.out.println(Files.exists(backup)); // prints "true"
       System.out.println(new String(Files.readAllBytes(backup))); // prints its bytes
       System.out.println(backup.toString()); // prints "file.bin.BAK"
    } catch (IOException ex) {
       System.err.println(ex);
    }
}

尝试显示正确的可编译
main
代码-您的意思是根本不会引发异常,但由于许多未捕获的异常已编辑,处于当前状态的代码不会编译。刚刚用try-catch包围了主代码。您是否尝试捕获常规异常以查看它是否引发意外类型的异常?显然,不要永久地执行此操作。@AndrewS-操作只抛出IOException,否则它将落在未捕获的异常上,但构建以某种方式成功完成。好的,然后捕获这两个并查看。谢谢您的回答。我在第二个示例中就是这样做的,但问题是在创建备份后(在main外部),我需要处理原始文件(对象实例),因此它抛出ClosedFileSystemException。然后,调用方(在main外部)应该负责创建和关闭文件系统。否则,除了关闭和重新打开之外,没有其他解决方案了……这是可行的,但现在我知道为什么人们开始不喜欢Java了。。那个try行相当紧凑,有点迟钝(虽然不是你的错)。@Holger这又一次让我感到痛苦(我不再忘记我使用
文件系统失败了多少次)。假设这样一种情况:使用
文件系统
读取某个
URI
并返回
路径的方法;稍后,该方法的一些调用方使用此路径执行某些操作。由于我在访问
文件系统时使用了try with resource
——我几乎总是会收到
ClosedException
,而且我总是忘记我还必须将
文件系统
返回给调用者,以便他们关闭它。这种咆哮实际上更像是一个问题:有没有更干净的方法来处理这个问题。。。感谢you@Eugene当您返回一个
路径
时,您还返回了一个
文件系统
,因为每个
路径
都有一个
getFileSystem()
方法。实际问题是判断文件系统在使用后是否已关闭。无法返回专用类型的实例,该实例知道是否必须关闭文件系统。它可能有一个
Path getPath()
方法并实现
Closeable
,但如果不应关闭此特定文件系统(如默认文件系统),则不在
close()
上执行任何操作。然后,调用方不需要考虑它,并且可以始终使用
try(…){…}
public static Path createBackup(Path file) throws IOException {
    Path backup = file.resolveSibling(file.getFileName().toString()+".BAK");
    return Files.copy(file, backup, StandardCopyOption.REPLACE_EXISTING);
}
public static void main(String... args) {
    try(FileSystem fs = FileSystems.newFileSystem(Paths.get("a.zip"), null)) {
       Path f = fs.getPath("file.bin");
       Path backup = createBackup(f);

       System.out.println(Files.exists(backup)); // prints "true"
       System.out.println(new String(Files.readAllBytes(backup))); // prints its bytes
       System.out.println(backup.toString()); // prints "file.bin.BAK"
    } catch (IOException ex) {
       System.err.println(ex);
    }
}