[英]Dealing with unix symlink files on Windows filesystem
我目前正在開發一個 Java 項目,該項目應該允許用戶導出與 Windows 軟件 (.exe) 或 OS X 應用程序 (.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 之前?
當前循環遍歷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);
}
}
}
Windows文件系統使用與UNIX類似的方法來定義符號鏈接(如硬鏈接或軟鏈接),但它們不是100%兼容的。 你可以在這里閱讀更多相關內容: https : //msdn.microsoft.com/en-us/library/windows/desktop/aa365680(v = vs。85)。aspx你問的簡單答案 - 你不能只是按位復制鏈接具有相同的Unix特定位,因為Windows NTFS只是沒有它們。 JAVA也設計為在沙箱中工作,因此您無法訪問系統低級API以“制作”您想要的任何內容。 我不會用JAVA去做這樣的系統特定任務。 可能你不必。
取決於您在此項目中的角色,您可以重新定義應包含的包。 你真的需要里面的符號鏈接嗎? 可能更普遍的是有一些將不同部分映射在一起的“屬性”文件? 或者將其作為數據庫分發? 盡量不要依賴於系統特定的實現。
您將需要Windows特定的“非標准”(至少用於Java)方法來解決此問題,因為沒有標准的跨平台Java方法來解決它。 例如,您可以嘗試使用Runtime.exec
以及對“mklink”實用程序的調用。 “mklink”命令允許創建硬和軟(符號)鏈接以及結點的創建 - 基本上它創建了Windows文件系統可用的各種類型的重新解析點。 如果您願意訪問本機代碼,那么您也可以使用預先制作的JNA映射到Kernel32.dll
或編寫自定義映射到Kernel32.dll
並調用WinBase.h
提供的方法CreateSymbolicLink(LPTSTR,LPTSTR,DWORD)
。
一般來說,如果可能的話,我建議你盡量避免使用Windows上的符號鏈接和硬鏈接。
Symlinks和Hardlinks已經很晚才被引入Windows,對它的支持相當差:
因此,由於您只需要臨時(如您在評論中所寫)的符號鏈接,然后再次壓縮文件,我建議在解壓縮時創建自己的標記文件以表示符號鏈接,稍后在壓縮時將其轉換回來到ZIP文件中正確的UNIX符號鏈接。
已經 6 年了,如果你在 Windows 上壓縮 macOS 應用程序包,然后在 Windows 上解壓相同的 ZIP,它會保留 macOS 包中的別名文件(主要在 Frameworks 文件夾中)。
正如您所說,您還可以將 macOS 應用程序保留為 ZIP package,並讓用戶在需要時將其解壓縮(最有可能在 macOS 上),那么它也可以工作。
在 Linux 上壓縮 macOS 應用程序包並在 macOS 上解壓縮也可以,但在 Windows 上不起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.