public void ReadXmlFile () {string path = HttpContext.Current.Server.MapPath ("~ / App_Data"); // Находит местоположение App_Data на сервере. XmlTextReader reader = новый XmlTextReader (System.IO.Path.Combine (путь, XMLFile7.xml)); // Объединяет расположение App_Data и имя файла while (reader.Read ()) {switch (reader.NodeType) {case XmlNodeType.Element: break; case XmlNodeType.Text: columnNames.Add (reader.Value); ломать; case XmlNodeType.EndElement: break; }}}
Вы можете избежать первого оператора и просто указать имя пути в конструкторе XmlTextReader.
Массив C char name[8]
импортируется в Swift как кортеж:
(Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8)
Адрес name
совпадает с адресом name[0]
, а Swift сохраняет макет памяти структур, импортированных из C, как , подтвержденного инженером Apple Джо Гроффом:
... Вы можете оставить структуру, определенную на C, и импортировать ее в Swift. Swift будет уважать макет C.
Как следствие, мы можем передать адрес
record.name
, преобразованный в указательUInt8
, в инициализатор строки:var record = someFunctionReturningAStructRecord() // Swift 2: let name = withUnsafePointer(&record.name) { String.fromCString(UnsafePointer($0))! } // Swift 3: let name = withUnsafePointer(to: &record.name) { $0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: record.name)) { String(cString: $0) } }
ПРИМЕЧАНИЕ: Предполагается, что байты в
name[]
являются допустимой последовательностью UTF-8 с NUL-концами.
Вот решение, с которым я пришел, с использованием отражения, чтобы фактически преобразовать кортеж в [Int8] (см. Любой способ перебора кортежа в swift? ), а затем преобразует его в строку используя методыCString ... ().
func arrayForTuple<T,E>(tuple:T) -> [E] {
let reflection = reflect(tuple)
var arr : [E] = []
for i in 0..<reflection.count {
if let value = reflection[i].1.value as? E {
arr.append(value)
}
}
return arr
}
public extension String {
public static func fromTuple<T>(tuple:T) -> String? {
var charArray = arrayForTuple(tuple) as [Int8]
var nameString = String.fromCString(UnsafePointer<CChar>(charArray))
if nameString == nil {
nameString = String.fromCStringRepairingIllFormedUTF8(UnsafePointer<CChar>(charArray)).0
}
return nameString
}
}
Попробуйте следующее:
func asciiCStringToSwiftString(cString:UnsafePointer<UInt8>, maxLength:Int) -> String
{
var swiftString = String() // The Swift String to be Returned is Intialized to an Empty String
var workingCharacter:UnicodeScalar = UnicodeScalar(cString[0])
var count:Int = 0 // An Index Into the C String Array Starting With the First Character
while cString[count] != 0 // While We Haven't reached the End of the String
{
workingCharacter = UnicodeScalar(cString[count]) // Convert the ASCII Character to a Unicode Scalar
swiftString.append(workingCharacter) // Append the Unicode Scalar Version of the ASCII Character
count++ // Increment the Index to Look at the Next ASCII Character
if count > maxLength // Set a Limit In Case the C string was Not NULL Terminated
{
if printDebugLogs == true
{
swiftString="Reached String Length Limit in Converting ASCII C String To Swift String"
}
return swiftString
}
}
return swiftString // Return the Swift String
}
UnsafePointer<UInt8>
, это набор из 8 Int8
элементов, поэтому этот метод не решает мою проблему. Кроме того, класс String
имеет инициализатор init?(UTF8String: UnsafePointer<CChar>)
failable, который делает это точно.
– zneak
13 December 2014 в 06:35
glGetString
возвращает указатель. В struct
я имею дело с полем массива, которое сильно отличается от поля указателя. Как я уже сказал, тип поля, видимый Свифтом, (Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8)
, а не UnsafePointer<UInt8>
.
– zneak
13 December 2014 в 07:05
Фактически вы можете собрать кортеж в массив с помощью синтаксиса вариационных параметров Swift:
let record = getRecord()
let (int8s: Int8...) = myRecord // int8s is an [Int8]
let uint8s = int8s.map { UInt8($0) }
let string = String(bytes: uint8s, encoding: NSASCIIStringEncoding)
// myString == Optional("12345678")
let (int8s: Int8...)
? Действительно ли let (name : type) = exp
совпадает с let name : type = expr
?
– Martin R
13 December 2014 в 12:14
let (_, second, _, fourth, theRest: Int...) = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
– Nate Cook
14 December 2014 в 07:15
Swift 3. Использует только отражение. Эта версия перестает строить строку, когда она встречает нулевой байт. Протестировано.
func TupleOfInt8sToString( _ tupleOfInt8s:Any ) -> String? {
var result:String? = nil
let mirror = Mirror(reflecting: tupleOfInt8s)
for child in mirror.children {
guard let characterValue = child.value as? Int8, characterValue != 0 else {
break
}
if result == nil {
result = String()
}
result?.append(Character(UnicodeScalar(UInt8(characterValue))))
}
return result
}
Я только что испытал подобную проблему, используя Swift 3. (3.0.2). Я пытался преобразовать массив CChar, [CChar] в строку в Swift. Оказывается, Swift 3 имеет инициализатор строки, который примет cString.
Пример:
let a = "abc".cString(using: .utf8) // type of a is [CChar]
let b = String(cString: a!, encoding: .utf8) // type of b is String
print("a = \(a)")
print("b = \(b)")
приводит к
a = Необязательно ([97, 98, 99, 0])
b = Необязательный («abc»)
Обратите внимание, что функция cString в String приводит к необязательной. Он должен быть принудительно развернут при использовании в функции String.init, создающей b. И b также является необязательным ... что означает, что оба могут быть ноль, поэтому также следует использовать проверку ошибок.
record
нуждается в , чтобы быть изменчивым (объявлено с помощьюvar
), или компилятор Swift запускает странную ошибку. – zneak 13 December 2014 в 07:36withUnsafeBufferPointer
, но реализация кортежа не была документирована, насколько я могу судить. – Nate Cook 14 December 2014 в 07:20char name[8]
. – Martin R 14 December 2014 в 11:00