写入 ZIP 文件的文件仅在运行时可用 [Java]
File written to ZIP file available only during runtime [Java]
我在使用 Java 7 的 FileSystem
和 Files
API 将二进制文件写入简单 ZIP 存档时遇到问题。
执行写入操作时出现问题,完全没有抛出异常,文件未写入 ZIP 存档,但在运行时可用(Files.exists(backup)
returns true 并且有可能使用 Files.readAllBytes(backup)
).
读取文件
当程序关闭并重新启动时,该文件不再可用。
片段
此方法应该创建任何路径的备份,无论文件系统提供者是谁,'fails' 仅在 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 中实际上并不存在该文件。
编辑:
我设法使它工作,但有一个问题。下面的代码关闭文件系统,但写入正确。需要 "refresh"/"reopen" 文件系统。
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 明确说明要使用哪种文件系统提供程序。您可能想知道为什么是 jar 而不是 zip。在 Java 中,jar 文件实际上是 zip 文件,但具有不同的文件扩展名。因此 java 可以使用相同的机制来访问 zip 文件。
我用二进制文件和文本文件试过了,它似乎可以在我的 Win 10 机器上运行。只需更改 zip 文件的源目录 (///e:/a.zip) 以指向您的 zip 文件的位置。对我来说,file.bin.BAK 被写入了 eclipse 项目目录的根目录(您可能还想更改它以进行部署)。
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String... args) {
//Create URI to define the source as a Zip file.
//I've used jar because this is essentially a zip file.
Map<String, String> env = new HashMap<>();
env.put("create", "true");
URI uri = URI.create("jar:file:///e:/a.zip");
try{
//Build paths to source file in zip and externally.
Path pathInZipfile = FileSystems.newFileSystem(uri, env).getPath("/file.bin");
Path extPath = Paths.get("file.bin.BAK");
//If file does not exist create it.
if (! Files.exists(extPath))
Files.createFile(extPath);
//Copy the files over.
Files.copy( pathInZipfile, extPath,
StandardCopyOption.REPLACE_EXISTING );
}//end try
catch (IOException ex){
ex.printStackTrace();
}//enc catch
}//end main
}//end class
您应该在创建文件系统的调用方中使用 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);
}
}
我在使用 Java 7 的 FileSystem
和 Files
API 将二进制文件写入简单 ZIP 存档时遇到问题。
执行写入操作时出现问题,完全没有抛出异常,文件未写入 ZIP 存档,但在运行时可用(Files.exists(backup)
returns true 并且有可能使用 Files.readAllBytes(backup)
).
当程序关闭并重新启动时,该文件不再可用。
片段
此方法应该创建任何路径的备份,无论文件系统提供者是谁,'fails' 仅在 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 中实际上并不存在该文件。
编辑: 我设法使它工作,但有一个问题。下面的代码关闭文件系统,但写入正确。需要 "refresh"/"reopen" 文件系统。
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 明确说明要使用哪种文件系统提供程序。您可能想知道为什么是 jar 而不是 zip。在 Java 中,jar 文件实际上是 zip 文件,但具有不同的文件扩展名。因此 java 可以使用相同的机制来访问 zip 文件。
我用二进制文件和文本文件试过了,它似乎可以在我的 Win 10 机器上运行。只需更改 zip 文件的源目录 (///e:/a.zip) 以指向您的 zip 文件的位置。对我来说,file.bin.BAK 被写入了 eclipse 项目目录的根目录(您可能还想更改它以进行部署)。
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String... args) {
//Create URI to define the source as a Zip file.
//I've used jar because this is essentially a zip file.
Map<String, String> env = new HashMap<>();
env.put("create", "true");
URI uri = URI.create("jar:file:///e:/a.zip");
try{
//Build paths to source file in zip and externally.
Path pathInZipfile = FileSystems.newFileSystem(uri, env).getPath("/file.bin");
Path extPath = Paths.get("file.bin.BAK");
//If file does not exist create it.
if (! Files.exists(extPath))
Files.createFile(extPath);
//Copy the files over.
Files.copy( pathInZipfile, extPath,
StandardCopyOption.REPLACE_EXISTING );
}//end try
catch (IOException ex){
ex.printStackTrace();
}//enc catch
}//end main
}//end class
您应该在创建文件系统的调用方中使用 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);
}
}