我尝试过我的第一个Swift程序。它应该从带有参数和装载服务器卷的shell脚本运行。当我从Xcode启动程序时,在卷名(例如å,ä,ö)中有瑞典字符的参数,程序就可以正常工作。如果我从命令行启动程序,并在卷名中使用带有瑞典字符的参数,则挂载失败,它会在挂载点创建一个文件夹,并在“/ Volumes”中使用正确的名称。
为什么瑞典字符的参数不能在命令行中起作用?
代码:
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 :(得分:0)
如果您在将连接字符串的相关部分中的所有特殊字符传递给NSURL的初始化之前,它是否有效?
let encodedShareName = shareName.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
let sharePathRaw = "\(serverAddress)/\(encodedShareName!)"
答案 1 :(得分:0)
首先,您应该修复构建URL的方式。使用NSURLComponents
而不是连接和转义/引用字符串。从服务器URL字符串创建NSURLComponents
,然后从共享名称设置其path
属性,然后使用其url
属性获取URL对象。
其次,您需要检查NetFSMountURLSync()
的返回代码,以深入了解失败的原因。
第三,您的共享名称中的瑞典字符可以用两种不同的方式表示。例如,“Å”可能是单个Unicode字符,U + 00C5 LATIN CAPITAL LETTER A WITH RING ABOVE。以UTF-8编码,即字节0xC3 0x85。或者,它可能是两个Unicode字符:一个普通的A(U + 0041 LATIN CAPITAL LETTER A),然后是一个上面的组合环(U + 030A COMBINING RING ABOVE)。该序列的UTF-8将是0x41 0xCC 0x8A。
您输入角色的两个不同位置(Xcode的控制台窗格与终端窗口)可能会为相同的击键产生不同的实际字符。这意味着网址不一样。
同样的事情适用于您的共享名称中的其他瑞典字符。
您可以使用时髦的技巧在命令行中输入正确的字符,例如在$'\x41\xCC\x8A'
中使用bash
来获取第二种形式的“Å”。
由文件服务器决定它是否将两条路径视为相同。您的程序要么必须熟悉有问题的服务器并转换为其约定,要么尝试各种规范化策略(例如使用decomposedStringWithCanonicalMapping
或precomposedStringWithCanonicalMapping
)作为回退,如果挂载尝试失败,因为共享名称是不对的。