简体   繁体   中英

Swift NSData String Conversion Based on Subset of NSData

Situation

I'm working with binary data which has a string encoded in the middle. What I'm trying to do is extract this string so that I can both "set" and "get" it. I've come up with a methodology which seems a little funky (actually 3 options). I've included a playground code which you can look at.

I'm wondering if there is a "better" way to work with this data than what I've come up. Better means more efficient or clearer code-wise.

To read the data I do the following -

  1. make var rawData by converting the NSMutableData to UnsafeMutablePoitner<UInt8>
  2. Create var ptr : UnsafeMutablePointer<UInt8> from rawData.mutableBytes
  3. Create an array bytes of type UnsafeMutableBufferPointer<UInt8> from a combo of the 1st two variables
  4. Create a new array consisting of just the bytes containing the string bytes[19] - bytes[26]
  5. Extract this array into a string

Then to set the variable I have 3 methods but the one I think I would use is 1. Make a new string of 8 string 2. Create [UInt8] array of the characters of the string 3. Loop through each byte in the new array and set the value of the byte in the bytes array to the value in question

I'm assuming there is some way where I can be working directly with the "parent" byte array as opposed to making a sub-array to work with. Playground code is below. I'm looking for a cleaner way to do this and perhaps there is not one.

Thanks

Playground Code

import Cocoa
//import AppKit



///This is the raw data
var testBytes : [UInt8] = [0x14, 0x00, 0xAB, 0x45, 0x49, 0x1F, 0xEF, 0x15, 0xA8, 0x89, 0x78, 0x0F, 0x09, 0xA9, 0x07, 0xB0, 0x01, 0x20, 0x01, 0x4E, 0x38, 0x32, 0x35, 0x56, 0x20, 0x20, 0x20, 0x00]

///Convert into msgData
var msgData = NSMutableData(bytes: testBytes, length: testBytes.count)


// Store raw data into a byte array for messing with
var rawData: NSMutableData = NSMutableData(data: msgData)
var ptr: UnsafeMutablePointer<UInt8> = UnsafeMutablePointer<UInt8>(rawData.mutableBytes)
var bytes : UnsafeMutableBufferPointer<UInt8> = UnsafeMutableBufferPointer<UInt8>(start: ptr, count: rawData.length)


// Extract Callsign from the data stream
var callsignArray : [UInt8] = [bytes[19], bytes[20], bytes[21], bytes[22], bytes[23], bytes[24], bytes[25], bytes[26]]
var callsignString = NSString(bytes: callsignArray, length: callsignArray.count, encoding: NSUTF8StringEncoding)
let callsignString0 = callsignString!
println(callsignArray)
println("1. -- Initial Callsign [\(callsignString0)]")


//OPTION #1
// Edit Callsgin Array Directly (sketchy)
// And manually copy the bytes back into the base array
callsignArray[0] = 97
callsignArray[1] = 98
callsignArray[2] = 99
callsignArray[3] = 100

println(callsignArray)

// Write the new "bytes" back into the main array - there must be a better way
for (var i = 0; i <= 7; i++) {
    bytes[19+i] = callsignArray[i]
}

let callsign1 = NSString(bytes: callsignArray, length: callsignArray.count, encoding: NSUTF8StringEncoding)!

println("2. -- Modification of Bytes [\(callsign1)]")

//Option 3 - Go from String to Bytes

let callsign3 = "AABCDEF "
var buf = [UInt8](callsign3.utf8)

for (var i = 0; i <= 7; i++) {
    bytes[19+i] = buf[i]
}
println(rawData)

callsignArray = [bytes[19], bytes[20], bytes[21], bytes[22], bytes[23], bytes[24], bytes[25], bytes[26]]
callsignString = NSString(bytes: callsignArray, length: callsignArray.count, encoding: NSUTF8StringEncoding)

NSMutableData has methods to extract and replace sub-ranges:

// Get: 
let subData = msgData.subdataWithRange(NSMakeRange(19, 8))
let string = NSString(data: subData, encoding: NSUTF8StringEncoding)

// Set:
let newString = "AABCDEF "
let newData = newString.dataUsingEncoding(NSUTF8StringEncoding)!
msgData.replaceBytesInRange(NSMakeRange(19, 8), withBytes: newData.bytes, length: newData.length)

You can also operate on the [UInt8] array directly:

// Get:
let string = testBytes.withUnsafeBufferPointer {
    NSString(bytes: UnsafePointer($0.baseAddress + 19), length: 8, encoding: NSUTF8StringEncoding)
}

// Set:
testBytes.replaceRange(19 ... 26, with: Array(newString.utf8))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM