2016-11-06 62 views
1

我試過我的第一個Swift程序。它意味着從具有參數和裝載服務器卷的shell腳本運行。當我從卷名(例如å,ä,ö)中帶有瑞典字符參數的Xcode啓動程序時,該程序按照原樣運行。如果我從卷名中帶有瑞典語字符參數的命令行啓動程序,掛載失敗,它會在「/卷」中以正確的名稱在掛載點創建一個文件夾。爲什麼不使用NetFSMountURLSync命令行參數中的瑞典語字符?

爲什麼瑞典字符的參數不能在命令行中運行?

代碼:

import Foundation 
import NetFS 

func mountShare(serverAddress: String, shareName: String, userName: String, password: String) { 
    let fm = FileManager.default 
    let mountPoint = "/Volumes/".appendingFormat(shareName) 
    var isDir : ObjCBool = false 
    if fm.fileExists(atPath: mountPoint, isDirectory: &isDir) { 
     if isDir.boolValue { 
      unmount(mountPoint, 0) 
      print("Unmounted: \(mountPoint)") 
     } 
    } 
    let sharePathRaw = "\(serverAddress)/\(shareName)" 
    let sharePathWithPercentEscapes = sharePathRaw.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) 
    let sharePath = NSURL(string: sharePathWithPercentEscapes!) 
    let kNAUIOptionKey = "UIOption" 
    let kNAUIOptionNoUI = "NoUI" 
    let mount_options = NSMutableDictionary() 
    mount_options[kNAUIOptionKey] = kNAUIOptionNoUI 
    NetFSMountURLSync(sharePath as CFURL!, nil, userName as CFString!, password as CFString!, mount_options, nil, nil) 
} 

let argCount = CommandLine.argc 
if argCount == 5 { 
    let serverUrl = CommandLine.arguments[1] 
    let shareName = CommandLine.arguments[2] 
    let userName = CommandLine.arguments[3] 
    let password = CommandLine.arguments[4] 
    mountShare(serverAddress: "\(serverUrl)", shareName: "\(shareName)", userName: "\(userName)", password: "\(password)") 
} else { 
    print("Wrong number of arguments.") 
} 

實例開始的命令行程序,它的工作原理:

mountVolume "afp://my.server.com" "myVolume" "user" "password" 

實例啓動程序的命令行,不是作品:

mountVolume "afp://my.server.com" "myVolumeÅÄÖ" "user" "password" 

更多信息: 當我嘗試打印出比較值的所有變量時,一個來自Xcode的程序替代命令行並沒有什麼區別。但是,NetFSMountURLSync在命令行上以代碼2退出而不是0退出。

+0

從命令行運行時,「shareName」的實際值是多少? – rmaddy

+0

我有一個名爲「myVolumeÅÄÖ」的測試卷。 –

+0

這不是我問的。當你實際運行沒有Xcode的程序時,'shareName'變量的實際值是多少?根據您在答案下發布的評論,看起來您的問題是由可選值造成的。 – rmaddy

回答

0

如果您在將連接字符串的相關部分中的所有特殊字符傳遞給NSURL的init之前先轉義所有特殊字符,它會起作用嗎?

let encodedShareName = shareName.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) 
let sharePathRaw = "\(serverAddress)/\(encodedShareName!)" 
+0

無論字符如何,它都可以從Xcode或命令行工作。掛載點命名爲「/ Volumes/Optional(」myVolume「)。 –

+0

對不起,我忘記了可選。我已經修改了讀'let sharePathRaw =」\(serverAddress)/ \(encodedShareName!)的響應''' (帶'!') –

+0

它不適用於瑞典語字符的卷,它在/ Volumes /中創建一個空的文件夾,其名稱正確 這裏它是如何在/ Volumes /中看到一個工作卷,並且不成功安裝: 'ls -l /卷/' 'dr-x ------ 1 magnus staff 264 6 Nov 21:05 myVolume' 'd - x - x - x + 2 magnus wheel 68 6月11日21:03myVolumeÅÄÖ' –

0

首先,您應該修復如何構建URL。使用NSURLComponents而不是拼接和轉義/引用字符串。從服務器URL字符串創建一個NSURLComponents,然後從共享名稱中設置path屬性,然後使用其url屬性獲取URL對象。

其次,您需要檢查NetFSMountURLSync()的返回碼,以瞭解其失敗的原因。

第三,您的共享名稱中的瑞典字符可以用兩種不同的方式表示。例如,「Å」可能是單個Unicode字符,U + 00C5拉丁大寫字母A。以UTF-8編碼,即字節0xC3 0x85。或者,它可能是兩個Unicode字符:一個普通的A(U + 0041拉丁大寫字母A),後面跟着一個高於字符的組合環(U + 030A COMBINING RING ABOVE)。該序列的UTF-8將是0x41 0xCC 0x8A。

您輸入字符的兩個不同位置,Xcode的控制檯窗格與終端窗口可能會爲相同的擊鍵生成不同的實際字符。這意味着URL不一樣。

這種情況適用於您的共享名稱中的其他瑞典語字符。

您可以使用時髦技術在您的命令行上獲取正確的字符,例如使用bash中的$'\x41\xCC\x8A'獲取第二種形式的「Å」。

由文件服務器決定是否將兩條路徑視爲相同。如果由於共享名稱不正確而導致安裝嘗試失敗,則您的程序必須熟悉相關服務器並轉換爲其慣例,或嘗試各種規範化策略(例如,使用decomposedStringWithCanonicalMapping或​​)作爲回退。

+0

首先,我使用'NSURLComponents'構建了URL,它的工作原理沒有瑞典語字符,瑞典語字符'NetFSMountURLSync()'給我返回來自Xcode和命令l國家統計局。它使用了「U + 00C5拉丁文大寫字母A」的變體。在網址中。第二。當它失敗時,返回碼是2. 三。當我使用我的原始代碼,並從命令行發送'myVolume $'\ x41 \ XCC \ X8A \ x41 \ XCC \ x88 \ x4f \ XCC \ x88''它可以使用,但不能使用'myVolume $'\ XC3 \ X85 \ XC3 \ X84 \ XC3 \ x96''。 –

+0

謝謝你,我已經回答了我的問題,但會解決一些新問題......而且我需要嘗試更多的服務器。 –

相關問題