处理Windows文件系统上的unix符号链接文件

时间:2016-12-06 21:49:31

标签: java windows macos symlink zipfile

我目前正在开发一个Java项目,该项目应该允许用户导出与Windows软件(.exe)或OS X app(.app)捆绑在一起的项目,以将数据分发到其他工作站。 Windows和OS X软件都存储为压缩zip文件,并在导出项目时解压缩。我的问题是在Windows上解压缩OS X应用程序打破了捆绑框架内的符号链接。反过来,这会破坏应用程序的签名,并在OS X上启动应用程序时导致问题。

我正在使用Apache Commons压缩库解压缩包,这使我能够检测符号链接及其目标。使用OS X,我能够使用java.nio.file.Files中的方法重新创建符号链接,但是对于Windows,这将需要管理员权限,我有点犹豫要添加作为使用该软件的先决条件(即使启用,我也不相信这会起作用 - 没试过。)

我对链接被破坏的原因有一点了解,但如果我理解正确,Windows文件系统不包括对Unix符号链接的文件类型的支持,因此链接被解压缩为普通文件和在OS X上打开时将不再被识别为符号链接。

所以,我的问题是,我能以某种方式将符号链接文件按位按位复制到Windows文件系统,保留Unix特定位或者保留这些信息是不可能的吗?或者我应该只更改导出方法以将项目文件添加到现有zip文件,在这种情况下,可能会保留符号链接信息,直到在目标计算机上解压缩zip?

循环遍历ZipArchiveEntry的每个ZipFile的当前代码如下:

byte data[] = new byte[BUFFER];

Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();

while (entries.hasMoreElements()) {
    ZipArchiveEntry zipEntry = entries.nextElement();
    String destFilename = copyFolder + zipEntry.getName();
    File destFile = new File(destFilename);

    if (zipEntry.isUnixSymlink()) {             
        File target = new File(zipFile.getUnixSymlink(zipEntry));              
        try {   
            // Try to create symbolic link - currently only works with OS X
            Files.createSymbolicLink(destFile.toPath(), target.toPath());
            continue;
        } catch (Exception e) {
            System.out.println("Failed to create symbolic link: " + 
                destFile.getAbsolutePath() + " -> " + 
                target.getAbsolutePath());
        }
    }

    // If file
    int count;
    FileOutputStream fos = new FileOutputStream(destFile);

    try (BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER)) {
        InputStream is = zipFile.getInputStream(zipEntry);
        while ( (count = is.read(data, 0, BUFFER)) != -1) {
            dest.write(data, 0, count);
        }
    }
}

3 个答案:

答案 0 :(得分:3)

Windows文件系统使用与UNIX类似的方法来定义符号链接(如硬链接或软链接),但它们不是100%兼容的。您可以在此处详细了解:https://msdn.microsoft.com/en-us/library/windows/desktop/aa365680(v=vs.85).aspx   简单回答你的问题 - 你不能按位复制链接以拥有相同的Unix特定位,因为Windows NTFS只是没有它们。 JAVA还可以在沙盒中工作,因此您无法访问系统低级API,无论您想要什么,都可以使用#34;。我不会用JAVA去做这样的系统特定任务。可能你不需要。

取决于您在此项目中的角色,您可以重新定义应包含的内容。你真的需要里面的符号链接吗?可能是更普遍的拥有某种&#34;属性&#34;将不同部分映射到一起的文件?或者将其作为数据库分发?尽量不要依赖于系统特定的实现。

答案 1 :(得分:3)

由于没有标准的跨平台Java方法来解决此问题,因此您将需要Windows特定的和“非标准”(至少用于Java)方法来解决此问题。例如,您可以尝试在调用"mklink" utility的同时使用Runtime.exec。 “mklink”命令允许创建硬和软(符号)链接以及结点的创建 - 基本上它创建了Windows文件系统可用的各种类型的重新解析点。如果您愿意访问原生代码,那么您也可以使用预先制作的JNA mapping to Kernel32.dllwrite a custom mapping to Kernel32.dll并调用WinBase.h提供的方法CreateSymbolicLink(LPTSTR,LPTSTR,DWORD)

答案 2 :(得分:1)

一般来说,如果可能的话,我建议你尽量避免在Windows上使用符号链接和硬链接。

Symlinks和Hardlinks已经很晚才被引入Windows,对它的支持相当差:

  • 大多数Windows用户不希望文件系统中存在符号链接
  • 符号链接仅在NTFS文件系统上本地支持,而不在其他文件系统(FAT,exFAT,UDF)上或通过网络共享支持
  • 第三方工具(拉链,备份工具,云同步软件)以及一些Microsoft软件(例如文件版本历史记录,即Windows“Time Machine”;或复制/移动文件夹时的Windows资源管理器)无法应对符号链接或硬链接,解析它们或崩溃/显示错误消息。)
  • 创建它们所需的权限因Windows版本而异(在Windows 7上,普通用户可以创建符号链接(联结)到他可以访问的目录,但在Windows XP上,无论如何都需要管理员权限)

因此,由于您只需要临时(如您在评论中所写)的符号链接,然后再次压缩文件,我建议在解压缩时创建自己的标记文件来表示符号链接,以后再拉链时将它们转换回ZIP文件中的正确UNIX符号链接。