Как я могу преобразовать 2 значения из массива ByteArray Array & lt; UInt8 & gt; к 16-битовому целочисленному UInt16 в Swift 4? [Дубликат]

Вопрос в том, что хуже:

  • тупик или
  • неправильное значение?

Для финансовых баз данных, тупики намного хуже неправильных значений. Я знаю, что это звучит в обратном направлении, но выслушайте меня. Традиционным примером транзакций БД является обновление двух строк, вычитание из одного и добавление в другое. Это неправильно.

В финансовой базе данных вы используете деловые операции. Это означает добавление одной строки в каждую учетную запись. Крайне важно, чтобы эти транзакции завершились, и строки были успешно записаны.

Неправильное получение баланса аккаунта неправильно, это то, к чему подходит согласование на конец дня. И овердрафт с учетной записи гораздо более вероятен, потому что два банкомата используются одновременно, а не из-за незафиксированного чтения из базы данных.

При этом SQL Server 2005 исправил большинство ошибок, которые сделали NOLOCK необходимо. Поэтому, если вы не используете SQL Server 2000 или более раннюю версию, вам это не понадобится.

Дальнейшее чтение Версии уровня строк

25
задан zaph 12 August 2014 в 16:02
поделиться

6 ответов

Если вы хотите перейти через NSData, то он будет работать следующим образом:

let bytes:[UInt8] = [0x01, 0x02]
println("bytes: \(bytes)") // bytes: [1, 2]
let data = NSData(bytes: bytes, length: 2)
print("data: \(data)") // data: <0102>

var u16 : UInt16 = 0 ; data.getBytes(&u16)
// Or:
let u16 = UnsafePointer<UInt16>(data.bytes).memory

println("u16: \(u16)") // u16: 513

Альтернативно:

let bytes:[UInt8] = [0x01, 0x02]
let u16 = UnsafePointer<UInt16>(bytes).memory
print("u16: \(u16)") // u16: 513

Оба варианта предполагают, что байты находятся в

Обновление для Swift 3 (Xcode 8):

let bytes: [UInt8] = [0x01, 0x02]
let u16 = UnsafePointer(bytes).withMemoryRebound(to: UInt16.self, capacity: 1) {
    $0.pointee
}
print("u16: \(u16)") // u16: 513
40
ответ дан Martin R 3 September 2018 в 18:05
поделиться

Предполагая малое кодирование endian.

Чтобы преобразовать в UInt16 из [UInt8], вы можете сделать что-то вроде

var x: [UInt8] = [0x01, 0x02]
var y: UInt16 = 0
y += UInt16(x[1]) << 0o10
y += UInt16(x[0]) << 0o00

. Для преобразования в UInt32 этот шаблон распространяется на

var x: [UInt8] = [0x01, 0x02, 0x03, 0x04]
var y: UInt32 = 0
y += UInt32(x[3]) << 0o30
y += UInt32(x[2]) << 0o20
y += UInt32(x[1]) << 0o10
y += UInt32(x[0]) << 0o00

Восьмеричное представление величины сдвига дает хорошую индикацию о том, сколько полных байтов смещено (8 становится 0o10, 16 становится 0o20 и т. д.).

Это можно свести к следующему для UInt16:

var x: [UInt8] = [0x01, 0x02]
let y: UInt16 = reverse(x).reduce(UInt16(0)) {
    $0 << 0o10 + UInt16($1)
}

и для UInt32:

var x: [UInt8] = [0x01, 0x02, 0x03, 0x04]
let y: UInt32 = reverse(x).reduce(UInt32(0)) {
    $0 << 0o10 + UInt32($1)
}

Сокращенная версия также работает для UInt64, а также обрабатывает значения, в которых байтовая кодировка не использует все байты, такие как [0x01, 0x02, 0x03]

0
ответ дан Etan 3 September 2018 в 18:05
поделиться

В Swift 3 или более поздней версии вы можете преобразовать байты [UInt8] в Data и получить значение UInt16 с помощью withUnsafeBytes { $0.pointee }

Swift 3 или более поздней версии

extension Data {
    var uint16: UInt16 {
        return withUnsafeBytes { $0.pointee }
    }
}
< hr>
extension Collection where Element == UInt8 {
    var data: Data { return Data(self) }
}

let bytes: [UInt8] = [1, 2]
let uint16 = bytes.data.uint16
print(uint16) // 513
0
ответ дан Leo Dabus 3 September 2018 в 18:05
поделиться

Как насчет

let bytes:[UInt8] = [0x01, 0x02]
let result = (UInt16(bytes[1]) << 8) + UInt16(bytes[0])

С помощью цикла это легко обобщает на большие массивы байтов и может быть обернуто в функцию для удобочитаемости:

let bytes:[UInt8] = [0x01, 0x02, 0x03, 0x04]

func bytesToUInt(byteArray: [UInt8]) -> UInt {
  assert(byteArray.count <= 4)
  var result: UInt = 0
  for idx in 0..<(byteArray.count) {
    let shiftAmount = UInt((byteArray.count) - idx - 1) * 8
    result += UInt(byteArray[idx]) << shiftAmount
  }
  return result
}

println(bytesToUInt(bytes))    // result is 16909060
5
ответ дан pjs 3 September 2018 в 18:05
поделиться

Если байты находятся в объекте NSData, который вы можете сделать (предположим data:NSData):

var number: UInt16 = 0
data.getBytes(&number, length: sizeof(UInt16))

Метод getBytes записывает до двух байтов в ячейке памяти number ] (похоже на C memcpy. Это не приведет к сбою вашего приложения, если data не хватает байтов.

(изменить: не нужно использовать диапазон, если начинать с начала буфера)

3
ответ дан pqnet 3 September 2018 в 18:05
поделиться

Ответ Мартина R замечателен и хорошо обновлен для бета-версии 6. Однако, если вам нужно получить байты, которые не находятся в начале вашего буфера, предлагаемый метод withMemoryRebound не предлагает диапазон для повторной привязки. Мое решение для этого, например. выберите второй UInt16 из массива:

var val: UInt16 = 0
let buf = UnsafeMutableBufferPointer(start: &val, count: 1)
_ = dat.copyBytes(to: buf, from: Range(2...3))
2
ответ дан Teo Sartori 3 September 2018 в 18:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: