在swift中对特定值进行拆分或分块NSData

时间:2015-03-24 15:42:19

标签: ios swift nsdata

我正试图弄清楚如何在一个特定值上“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)

我猜想建立“范围”,但我想知道是否有更好的方法来解决这个问题?

Code Stub

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];

}

4 个答案:

答案 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))
        }
    }
}