我正试图弄清楚如何在一个特定值上“ch”NSData
。
7E 55 33 22 7E 7E 22 AE BC 7E 7E AA AA 00 20 00 22 53 25 A3 4E 7E
返回一个由3个[NSData]
类型元素组成的数组,其中元素为:
55 33 22
22 AE BC
AA AA 00 20 00 22 53 25 A3 4E
我知道我可以这样做:
var ptr = UnsafePointer<UInt8>(data.bytes)
var bytes = UnsafeBufferPointer<UInt8>(start: ptr, count: data.length)
我猜想通过做类似的比较来迭代:
bytes[1] == UInt8(0x7E)
我猜想建立“范围”,但我想知道是否有更好的方法来解决这个问题?
private fund chunkMessage(data: NSData) -> [NSData] {
var ptr = UnsafePointer<UInt8>(data.bytes)
var bytes = UnsafeBufferPointer<UInt8>(start: ptr, count: data.length)
var ret = []
// DO SOME STUFF
return ret as! [NSData];
}
答案 0 :(得分:5)
我遇到了类似的情况,但我只是想按照特定的大小来分块我的数据,这里是我如何在swift 2.0中使用它。这假定&#34;数据&#34;属于NSData类型,并且已经填充了要拆分的信息:
let length = data.length
let chunkSize = 1048576 // 1mb chunk sizes
var offset = 0
repeat {
// get the length of the chunk
let thisChunkSize = ((length - offset) > chunkSize) ? chunkSize : (length - offset);
// get the chunk
let chunk = data.subdataWithRange(NSMakeRange(offset, thisChunkSize))
// -----------------------------------------------
// do something with that chunk of data...
// -----------------------------------------------
// update the offset
offset += thisChunkSize;
} while (offset < length);
希望它有助于某人
答案 1 :(得分:4)
可能有许多可能的解决方案。一种直截了当的方式,使用
NSData
方法,将是
func chunkMessage(data: NSData, var separator : UInt8) -> [NSData] {
let sepdata = NSData(bytes: &separator, length: 1)
var chunks : [NSData] = []
// Find first occurrence of separator:
var searchRange = NSMakeRange(0, data.length)
var foundRange = data.rangeOfData(sepdata, options: nil, range: searchRange)
while foundRange.location != NSNotFound {
// Append chunk (if not empty):
if foundRange.location > searchRange.location {
chunks.append(data.subdataWithRange(NSMakeRange(searchRange.location, foundRange.location - searchRange.location)))
}
// Search next occurrence of separator:
searchRange.location = foundRange.location + foundRange.length
searchRange.length = data.length - searchRange.location
foundRange = data.rangeOfData(sepdata, options: nil, range: searchRange)
}
// Check for final chunk:
if searchRange.length > 0 {
chunks.append(data.subdataWithRange(searchRange))
}
return chunks
}
正如评论中已经提到的,您可以使用Swift数组 代替。这是一个可能的实现:
func chunkMessage(data: NSData, separator : UInt8) -> [[UInt8]] {
let bytes = UnsafeBufferPointer<UInt8>(start: UnsafePointer(data.bytes), count: data.length)
// Positions of separator bytes:
let positions = filter(enumerate(bytes), { $1 == separator } ).map( { $0.0 } )
// Non-empty ranges between the separator bytes:
let ranges = map(Zip2([-1] + positions, positions + [bytes.count])) {
(from : Int, to : Int) -> (Int, Int) in
(from + 1, to - from - 1)
}.filter( { $1 > 0 } )
// Byte chunks between the separator bytes:
let chunks = map(ranges) {
(start: Int, count : Int) -> [UInt8] in
Array(UnsafeBufferPointer(start: bytes.baseAddress + start, count: count))
}
return chunks
}
我留给你测试哪一个表现更好:)
答案 2 :(得分:4)
基于adan1985使用的Swift 3解决方案
150px
答案 3 :(得分:1)
Swift 3这样可行,扩展名为Data
//: Playground - noun: a place where people can play
import Cocoa
import Foundation
var str = "Hello, playground"
let d : Data = Data(bytes: [0x7E, 0x55, 0x33, 0x22, 0x7E, 0x7E, 0x22, 0xAE, 0xBC, 0x7E, 0x7E, 0xAA, 0xAA, 0x00, 0x20, 0x00, 0x22, 0x53, 0x25, 0xA3, 0x4E, 0x7E])
let f = d.separateData(bySeparator: 0x7E)
print(f) // [[0x55, 0x33, 0x22],[0x22, 0xAE, 0xBC],[0xAA, 0xAA, 0x00, 0x20, 0x00, 0x22, 0x53, 0x25, 0xA3, 0x4E]
//
// Data+Separate.swift
// Created by Julian Bleecker on 6/7/17.
//
public extension Data {
/// Separate data into an array of an array of Int8
func separateData(bySeparator : UInt8) -> [[UInt8]] {
let bytes = [UInt8](self)
let split = bytes.split(separator: bySeparator)
let bunks = split.enumerated().map( { $0.1 } )
let chunks = bunks.enumerated().map( {
Data.init($0.element).toArray(type: UInt8.self)
})
return chunks
}
/// Bonus. Convert to an array of Strings which would be separated by nulls
func separateDataToStrings(encoding: String.Encoding) -> [String] {
let strunks: [String] = self.separateData(bySeparator: 0x00).enumerated().map( {
let d: Data = Data.init(bytes: $0.element)
return String(data: d, encoding: .utf8)!
})
return strunks
}
func toArray<T>(type: T.Type) -> [T] {
return self.withUnsafeBytes {
[T](UnsafeBufferPointer(start: $0, count: self.count/MemoryLayout<T>.stride))
}
}
}