Java实现Zip文件属性写入/读取版本信息的方案咨询
First off, Java's core libraries don’t directly support modifying Windows-specific extended file properties (like the "Product Version" shown in your screenshot). But you absolutely can pull this off using JNA (Java Native Access) to interact with Windows APIs. Alternatively, there are cross-platform approaches that avoid OS lock-in, which is usually better if your zip files need to work across systems.
Approach 1: Windows-Specific Extended Properties with JNA
This method lets you edit the Windows file properties directly. Here’s how to implement it:
Step 1: Add JNA Dependencies
If using Maven, add these to your pom.xml:
<dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>5.13.0</version> </dependency> <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna-platform</artifactId> <version>5.13.0</version> </dependency>
Step 2: Write Product Version to Zip File
After creating your zip, use this utility class to set the version property:
import com.sun.jna.platform.win32.*; import com.sun.jna.WString; public class WindowsFilePropertySetter { public static void setProductVersion(String filePath, String version) { Shell32 shell32 = Shell32.INSTANCE; Ole32.INSTANCE.CoInitialize(null); try { IShellItem2 shellItem = Shell32Util.createShellItem2(filePath); // Property key for Windows' Product Version field PropertyKey productVersionKey = new PropertyKey( new Guid.GUID("56A3372E-CE9C-11D2-9F0E-006097C686F6"), 13 ); shellItem.SetString(productVersionKey, new WString(version)); } finally { Ole32.INSTANCE.CoUninitialize(); } } }
Update your existing zip code to call this after zipping:
try { Path inputFilePath = Paths.get(exportFilePath); Path outputFilePath = Paths.get(outputDirPath, String.format("%s.%s", inputFilePath.getFileName(), EXPORT_EXTENSION)); fileZipper.zipIt(inputFilePath, outputFilePath); // Set product version once zip is created WindowsFilePropertySetter.setProductVersion(outputFilePath.toString(), "1.2.3"); // Replace with your version log.info("Zipping and version tagging completed."); } catch (IOException e) { log.error("Error during zipping.", e); }
Step 3: Read Product Version
To retrieve the version later:
public class WindowsFilePropertyReader { public static String getProductVersion(String filePath) { Shell32 shell32 = Shell32.INSTANCE; Ole32.INSTANCE.CoInitialize(null); try { IShellItem2 shellItem = Shell32Util.createShellItem2(filePath); PropertyKey productVersionKey = new PropertyKey( new Guid.GUID("56A3372E-CE9C-11D2-9F0E-006097C686F6"), 13 ); Variant.VARIANT variant = new Variant.VARIANT(); shellItem.GetProperty(productVersionKey, variant); return variant.getValue().toString(); } finally { Ole32.INSTANCE.CoUninitialize(); } } }
Note: Wrap this code in OS checks (e.g., System.getProperty("os.name").contains("Windows")) if your app runs on non-Windows systems.
Approach 2: Cross-Platform Alternatives
Since zip files are designed to work across OSes, these methods are more portable and maintainable:
Option 1: Add a Metadata File Inside the Zip
Include a small text or JSON file (like version.txt or metadata.json) inside the zip to store version info. This is straightforward and works everywhere.
Modify your zip logic to add this file:
import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public void zipWithVersion(Path inputFile, Path outputZip, String version) throws IOException { try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(outputZip))) { // Add your main input file ZipEntry mainEntry = new ZipEntry(inputFile.getFileName().toString()); zos.putNextEntry(mainEntry); Files.copy(inputFile, zos); zos.closeEntry(); // Add version metadata file ZipEntry versionEntry = new ZipEntry("version.txt"); zos.putNextEntry(versionEntry); String versionContent = String.format("Product Version: %s", version); zos.write(versionContent.getBytes(StandardCharsets.UTF_8)); zos.closeEntry(); } }
To read the version, either extract the zip or read the version.txt entry directly without extracting.
Option 2: Use the Zip File Comment
Zip files support a global comment field—perfect for storing short version strings.
Writing the Comment:
try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(outputZip))) { // Your existing zipping logic here... // Attach version info to the zip comment zos.setComment(String.format("Product Version: %s", "1.2.3")); }
Reading the Comment:
try (java.util.zip.ZipFile zipFile = new java.util.zip.ZipFile(outputZip.toFile())) { String comment = zipFile.getComment(); if (comment != null && comment.startsWith("Product Version:")) { String version = comment.substring("Product Version:".length()).trim(); log.info("Found product version: {}", version); } }
This avoids extra files and works cross-platform, with a comment size limit of ~65KB (plenty for version strings).
Option 3: Embed Version in the Filename
A quick-and-dirty approach: include the version directly in the zip filename (e.g., exported-data_v1.2.3.zip). It’s visible at a glance but less flexible if you need to update the version without renaming the file.
Summary
- Windows-only: Use JNA if you need the version to appear in Windows file explorer details.
- Cross-platform: Prefer adding a metadata file or using the zip comment—these are simpler, more portable, and work on all operating systems.
内容的提问来源于stack exchange,提问作者Mitul Maheshwari

