2016-12-06 122 views
4

我目前正在開發一個Java項目,該項目應該使用戶能夠導出與Windows軟件(.exe)或OS X應用程序(.app)捆綁在一起的項目,以便將數據分發給其他工作站。 Windows和OS X軟件都存儲爲壓縮的zip文件,並且在項目導出的情況下未壓縮。我的問題是,在Windows上解壓縮OS X應用程序將打破捆綁框架內的符號鏈接。這反過來打破了應用程序的簽名,並導致應用程序在OS X上啓動時出現問題。處理Windows文件系統上的unix符號鏈接文件

我使用Apache Commons壓縮庫來解壓縮包,這使我能夠檢測符號鏈接及其目標。使用OS X,我可以使用java.nio.file.Files中的方法重新創建符號鏈接,但對於Windows,這需要管理員權限,我有點猶豫是否需要添加這些權限作爲使用該軟件的先決條件(即使啓用,我不相信這會奏效 - 還沒有嘗試過)。

我對鏈接被破壞的原因有一點了解,但是如果我理解正確的話,Windows文件系統不包括對Unix符號鏈接文件類型的支持,因此鏈接解壓縮爲普通文件並且在OS X上打開時將不再被識別爲符號鏈接。

所以,我的問題是,我可以以某種方式將符號鏈接文件按位複製到Windows文件系統,保留Unix特定位或保留這些信息不可能?或者,我應該改變導出方法以將項目文件添加到現有的zip文件,在這種情況下,符號鏈接信息可能會保留,直到目標機器上的zip被解壓縮爲止?

當前的代碼循環在ZipFile的每個ZipArchiveEntry是如下:

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); 
     } 
    } 
} 
+0

您能告訴我們更多關於這個工作流程的用法嗎(例如,什麼類型的設備是Windows上未壓縮的ZIP設備,以及該設備以後如何傳輸到Mac)?我很困惑,因爲在Windows上,只有NTFS文件系統支持符號鏈接,而FAT32則不支持,所以如果您將Windows計算機上的ZIP解壓到USB密鑰上,如果USB密鑰是FAT格式的,則符號鏈接將會丟失。如果是NTFS格式,Mac將(默認情況下)無法讀取它。 此外,任何用戶都可以對目錄進行符號鏈接,您只需要將符號鏈接文件的Admin權限。 – mihi

+0

另外,如果您在Windows資源管理器中複製文件/符號鏈接,則無論所涉及的文件系統如何(即使NTFS轉換爲NTFS),該副本也不會被符號鏈接。 – mihi

+0

目前的工作流程如下: 1)數據的查看軟件(OS X和Windows版本)之前被解壓縮到出口 2)導出的數據旁邊被保存到瀏覽軟件 3)整個事情再次被壓縮到一個zip文件,發送到FTP服務器。有關如何下載軟件包的說明通過電子郵件發送給接收方 並且問題: 4)OS X用戶無法打開查看軟件,因爲OS X應用程序在windows上的解壓縮 - >壓縮過程中被破壞。 – pnkkr

回答

3

Windows文件系統使用類似的方法爲UNIX定義符號鏈接是什麼(如硬或軟鏈接),但他們不是100%兼容的。你可以在這裏閱讀更多關於這個:https://msdn.microsoft.com/en-us/library/windows/desktop/aa365680(v=vs.85).aspx 對你的問題的簡單答案 - 你不能只是按位複製鏈接以具有相同的Unix特定位,因爲Windows NTFS只是沒有它們。 JAVA也被設計成在沙箱中工作,所以你無法訪問系統底層的API來製作「任何你想要的」。我不會用JAVA去做這種系統特定的任務。可能你不會需要。

取決於您在此項目中的角色,您可以重新定義應該包含的包。你真的需要符號鏈接嗎?可能有更普遍的做法是將不同部分映射到一起的某種「財產」文件?或者將其作爲數據庫分發?儘量不要依賴於系統特定的實現。

+0

我相信在這種情況下,它不適合我來決定一個包是否應該包含符號鏈接 - 這是用捆綁框架做事情的蘋果方式。 https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html 但是,感謝您的有用答案! :) – pnkkr

+0

屬性文件是一個好主意,如果你想讓你的應用跨平臺的話,這是一件好事。蘋果的方式顯然只適用於Apple ... 您可以在鏈接創建失敗時使用屬性文件? – Matthieu

3

由於沒有標準的跨平臺Java解決方法,您將需要一個Windows專用和「非標準」(至少用於Java)方法來解決此問題。例如,您可以嘗試使用Runtime.exec以及致電"mklink" utility。 「mklink」命令允許創建硬和軟(符號)鏈接以及創建連接點 - 基本上它創建了Windows文件系統可用的各種類型的重新解析點。如果您願意訪問本地代碼,那麼您也可以使用預製的JNA mapping to Kernel32.dllwrite a custom mapping to Kernel32.dll並撥打WinBase.h提供的方法CreateSymbolicLink(LPTSTR,LPTSTR,DWORD)

1

一般來說,如果可能的話,我建議您完全避免Windows上的符號鏈接和硬鏈接。

符號鏈接和硬連接已被引入到Windows挺晚了,對它的支持比較差:

  • 大多數Windows用戶不希望在他們的文件系統中的符號鏈接
  • 符號鏈接僅在本地的支持NTFS文件系統,而不是其他文件系統(FAT,exFAT,UDF)或通過網絡共享第三方工具(Zipper,備份工具,雲同步軟件)以及一些Microsoft軟件(例如文件版本歷史記錄,即Windows ''Time Machine';或者複製/移動文件夾時的Windows資源管理器)無法應付sym鏈接或硬鏈接,解決它們或崩潰/顯示錯誤消息)。
  • 權限創建它們的Windows版本而異所需的(在Windows 7上,普通用戶可以創建符號鏈接(路口)到一個目錄下,他可以訪問,但在Windows XP中,你需要在任何情況下,管理員權限)

因此,因爲您只需要暫時(如您在註釋中所寫的)符號鏈接,然後再次壓縮文件,我建議您在解壓縮時創建自己的標記文件來表示符號鏈接,並且以後在壓縮時轉換他們回到ZIP文件中正確的UNIX符號鏈接。

相關問題