根据 swift 中的特定值拆分或分块 NSData
Splitting or Chunking NSData on specific value(s) in swift
我正在尝试弄清楚如何根据特定值“分块”NSData
。
输入数据
7E 55 33 22 7E 7E 22 AE BC 7E 7E AA AA 00 20 00 22 53 25 A3 4E 7E
输出数据
Returns 类型为 [NSData]
的 3 个元素的数组,其中元素为:
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];
}
可能有很多可能的解决方案。一种直接的方式,使用
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), { == separator } ).map( { [=11=].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( { > 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
}
我留给你来测试哪个表现更好:)
我 运行 遇到了类似的情况,但我只是想按特定大小对数据进行分块,下面是我如何让它在 swift 2.0 中工作。这假设 "data" 是 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);
希望对大家有所帮助
Swift 你使用的基于 adan1985 的 3 个解决方案
let length = data.count
let chunkSize = 500
var offset = 0
repeat {
// get the length of the chunk
let thisChunkSize = ((length - offset) > chunkSize) ? chunkSize : (length - offset);
// get the chunk
let chunk = data.subdata(in: offset..<offset + thisChunkSize )
// -----------------------------------------------
// do something with that chunk of data...
// -----------------------------------------------
// update the offset
offset += thisChunkSize;
} while (offset < length);
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( { [=10=].1 } )
let chunks = bunks.enumerated().map( {
Data.init([=10=].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: [=10=].element)
return String(data: d, encoding: .utf8)!
})
return strunks
}
func toArray<T>(type: T.Type) -> [T] {
return self.withUnsafeBytes {
[T](UnsafeBufferPointer(start: [=10=], count: self.count/MemoryLayout<T>.stride))
}
}
}
我正在尝试弄清楚如何根据特定值“分块”NSData
。
输入数据
7E 55 33 22 7E 7E 22 AE BC 7E 7E AA AA 00 20 00 22 53 25 A3 4E 7E
输出数据
Returns 类型为 [NSData]
的 3 个元素的数组,其中元素为:
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];
}
可能有很多可能的解决方案。一种直接的方式,使用
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), { == separator } ).map( { [=11=].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( { > 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
}
我留给你来测试哪个表现更好:)
我 运行 遇到了类似的情况,但我只是想按特定大小对数据进行分块,下面是我如何让它在 swift 2.0 中工作。这假设 "data" 是 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);
希望对大家有所帮助
Swift 你使用的基于 adan1985 的 3 个解决方案
let length = data.count
let chunkSize = 500
var offset = 0
repeat {
// get the length of the chunk
let thisChunkSize = ((length - offset) > chunkSize) ? chunkSize : (length - offset);
// get the chunk
let chunk = data.subdata(in: offset..<offset + thisChunkSize )
// -----------------------------------------------
// do something with that chunk of data...
// -----------------------------------------------
// update the offset
offset += thisChunkSize;
} while (offset < length);
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( { [=10=].1 } )
let chunks = bunks.enumerated().map( {
Data.init([=10=].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: [=10=].element)
return String(data: d, encoding: .utf8)!
})
return strunks
}
func toArray<T>(type: T.Type) -> [T] {
return self.withUnsafeBytes {
[T](UnsafeBufferPointer(start: [=10=], count: self.count/MemoryLayout<T>.stride))
}
}
}