1. import org.jboss.netty.buffer.{ChannelBuffers, ChannelBuffer}
  2. import java.nio.charset.Charset
  3. import BigDecimal.RoundingMode._
  4. /*
  5. * 采用LittleEndian字节顺序。结构为控制字节+附加字节
  6. * 控制字节
  7. * 7 符号位
  8. * 6-4 数据字节数量,在实际数据字节中保存原始数据的绝对值
  9. * 3-0 特定小整数保留位,0-15的数字可以不使用数据字节直接在控制字节中表示
  10. *
  11. * 范围截断。由于控制字节的限制,最多附加4bit + 7个字节(即60bit)的数据,如果超过范围,则进行截断。
  12. */
  13.  
  14. class BitCompress(buf: ChannelBuffer) {
  15. def compressLong(in: Long) {
  16. //抽取符号位、如果为负值则取绝对值,同时进行范围截断
  17. var (control, abs) = {
  18. val MaxAbsValue = 0x0fffffffffffffffl //60bit
  19. if (in < 0) (0x80.toByte, (-in) & MaxAbsValue)
  20. else (0x00.toByte, in & MaxAbsValue)
  21. }
  22.  
  23. //附加数据缓冲区
  24. val additionalBuffer = ChannelBuffers.buffer(8)
  25.  
  26. //去除待压缩数据中多余的0
  27. var additionalLength = 0 //为方便,将控制字节中的附加数据也作为一个附加数据处理,存储附加数据个数时应减1
  28. if (abs == 0) additionalLength += 1 //0无法进入else中的循环,无法为附加数据长度赋值,因而特殊处理
  29. else {
  30. val BytesOfLong = 8
  31. for (i <- 1 to BytesOfLong) {
  32. val dataByte = ((abs >>> (BytesOfLong - i) * 8) & 0xff).toByte
  33. if ((additionalLength != 0) || (dataByte != 0)) {
  34. //有效数据开始:附加数据不为空或者字节数据不为0
  35.  
  36. if (additionalLength != 0) {
  37. additionalBuffer.writeByte(dataByte)
  38. additionalLength += 1
  39. }
  40. else {
  41. //附加数据为空,有可能在控制字节中写入数据
  42. //高4位有数据,为偶数个4bit,控制字节低4bit不用存放数据
  43. //高4位没有数据,为奇数个4bit,控制字节低4bit需要存放数据
  44. if ((dataByte & 0xf0) != 0) {
  45. additionalBuffer.writeByte(dataByte)
  46. additionalLength += 2
  47. }
  48. else {
  49. control = (control | dataByte).toByte
  50. additionalLength += 1
  51. }
  52. }
  53. }
  54. }
  55. }
  56.  
  57. //附加数据长度
  58. additionalLength -= 1 //为方便,将控制字节中的附加数据也作为一个附加数据处理,存储附加数据个数时应减1
  59. control = (control | (additionalLength << 4)).toByte
  60.  
  61. //写入结果
  62. buf.writeByte(control)
  63. if (additionalLength != 0) buf.writeBytes(additionalBuffer)
  64. }
  65.  
  66. //压缩数据
  67. def <-<(in: Byte) { compressLong(in.toLong) }
  68. def <-<(in: Short) { compressLong(in.toLong) }
  69. def <-<(in: Int) { compressLong(in.toLong)}
  70. def <-<(in: Long) { compressLong(in) }
  71.  
  72. //压缩BigDecimal数据
  73. def <-<(in: BigDecimal) {
  74. compressLong(in.setScale(0, HALF_UP).toLong)
  75. }
  76.  
  77. //压缩字符串(以0为结尾标志)
  78. def compressString(bytes: Array[Byte]) {
  79. buf.writeBytes(bytes)
  80. buf.writeByte(0)
  81. }
  82.  
  83. def <-<(bytes: Array[Byte]) { compressString(bytes) }
  84.  
  85. //写入数据
  86. def <--(in: Byte) { buf.writeByte(in) }
  87. def <--(in: Short) { buf.writeShort(in) }
  88. def <--(in: Int) { buf.writeInt(in) }
  89. def <--(in: Long) { buf.writeLong(in) }
  90. def <--(in: Float) { buf.writeFloat(in) }
  91. def <--(in: Double) { buf.writeDouble(in) }
  92.  
  93. //解压Long数据
  94. def decompressLong() = {
  95. //控制字节
  96. //7 符号位
  97. //6-4 数据字节数,数据字节中保存原始数据的绝对值
  98. //3-0 特定小整数保留位,0-15的数字可以不使用数据字节直接在控制字节中表示
  99. val control = buf.readByte()
  100. val negative = (control & 0x80) == 0x80 //是否为负数
  101.  
  102. //附加数据长度
  103. val additionalLength = (control & 0x70) >>> 4
  104.  
  105. //控制字节所包含的附加数据
  106. var result: Long = control.toLong & 0x0f
  107.  
  108. //解压
  109. for (i <- 1 to additionalLength) {
  110. result <<= 8
  111. result |= (buf.readByte().toLong & 0xffL) //byte转为Long时,如为负数则默认填充位为1
  112. }
  113.  
  114. //符号
  115. if (negative) result = -result
  116.  
  117. result
  118. }
  119.  
  120. def decompressString(charsetName: String = "GBK") = {
  121. val dup = buf.duplicate()
  122.  
  123. var length = 0
  124. var done = false
  125. while (dup.readable() && !done) {
  126. if (dup.readByte() != 0) length += 1
  127. else done = true
  128. }
  129.  
  130. val result = buf.readBytes(length).toString(Charset.forName(charsetName))
  131. buf.skipBytes(1)
  132.  
  133. result
  134. }
  135.  
  136. def readByte() = buf.readByte()
  137. def readShort() = buf.readShort()
  138. def readInt() = buf.readInt()
  139. def readLong() = buf.readLong()
  140. def readFloat() = buf.readFloat()
  141. def readDouble() = buf.readDouble()
  142. }

行情二进制写

  1. import java.nio.ByteOrder
  2. import java.util
  3.  
  4. import org.jboss.netty.buffer.ChannelBuffers
  5.  
  6. class SnapshotBuffer() {
  7.  
  8. def read(bytes: Array[Byte]): Snapshot = {
  9. null
  10. }
  11.  
  12. def write(snap: Snapshot): Array[Byte] = {
  13. val bufferSize = 1024 * 1024
  14. val buffer = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, bufferSize)
  15. val bc = new BitCompress(buffer)
  16. val points = 10000
  17.  
  18. bc.compressString(snap.from.getBytes("UTF-8"))
  19. bc <-- snap.totalSn
  20. bc <-- snap.exchangeSn
  21. bc <-- snap.varietySn
  22.  
  23. val year = snap.dateTime.getYear
  24. val month = snap.dateTime.getMonthOfYear
  25. val day = snap.dateTime.getDayOfMonth
  26. val date = year * 10000 + month * 100 + day
  27. val hour = snap.dateTime.getHourOfDay
  28. val minute = snap.dateTime.getMinuteOfHour
  29. val second = snap.dateTime.getSecondOfMinute
  30. val mmsec = hour * 10000 + minute * 100 + second
  31.  
  32. bc.compressLong(date)
  33. bc.compressLong(mmsec)
  34. bc.compressLong(snap.exchangeType.id)
  35. bc.compressLong(snap.varietyType.id)
  36. bc.compressLong(snap.marketStatus.id)
  37. bc.compressLong(snap.snapshots.size)
  38.  
  39. snap.snapshots.foreach { item =>
  40. bc <-< 4
  41.  
  42. //不压缩
  43. bc <-- (item.dateTime.getMillis / 1000).toInt
  44. bc <-- item.marketId.id.toShort
  45.  
  46. //字符串以0结束
  47. bc.compressString(item.symbol.getBytes("UTF-8"))
  48. bc.compressString(item.name.getBytes("UTF-8"))
  49.  
  50. bc <-< item.prevClose * points
  51. bc <-< (item.open - item.prevClose) * points
  52. bc <-< (item.high - item.prevClose) * points
  53. bc <-< (item.low - item.prevClose) * points
  54. bc <-< (item.close - item.prevClose) * points
  55.  
  56. //不压缩
  57. bc <-- item.volume.toFloat
  58. bc <-- item.amount.toFloat
  59.  
  60. //保留2位压缩
  61. bc <-< item.pe * 100
  62.  
  63. val bids = Array.fill(5)(new OrderBook(0, 0))
  64. val asks = Array.fill(5)(new OrderBook(0, 0))
  65.  
  66. item.bids.toArray.copyToArray(bids)
  67. item.asks.toArray.copyToArray(asks)
  68.  
  69. val buyPrice = bids(0).price
  70. bc <-< buyPrice * points
  71. bc <-< (bids(1).price - buyPrice) * points
  72. bc <-< (bids(2).price - buyPrice) * points
  73. bc <-< (bids(3).price - buyPrice) * points
  74. bc <-< (bids(4).price - buyPrice) * points
  75.  
  76. bc <-< bids(0).lots
  77. bc <-< bids(1).lots
  78. bc <-< bids(2).lots
  79. bc <-< bids(3).lots
  80. bc <-< bids(4).lots
  81.  
  82. bc <-< (asks(0).price - buyPrice) * points
  83. bc <-< (asks(1).price - buyPrice) * points
  84. bc <-< (asks(2).price - buyPrice) * points
  85. bc <-< (asks(3).price - buyPrice) * points
  86. bc <-< (asks(4).price - buyPrice) * points
  87.  
  88. bc <-< asks(0).lots
  89. bc <-< asks(1).lots
  90. bc <-< asks(2).lots
  91. bc <-< asks(3).lots
  92. bc <-< asks(4).lots
  93.  
  94. bc <-< item.tradeLots
  95. bc <-< {
  96. if (item.suspended) 1 else 0
  97. }
  98. bc <-< item.holds
  99. bc <-< 0
  100. }
  101.  
  102. util.Arrays.copyOf(buffer.array, buffer.writerIndex)
  103.  
  104. }
  105. }

其中copyOf方法是将buffer复制到一个新数组,但是把多分配的size删除。

行情二进制的抽取

  1. object SnapshotWrapper {
  2.  
  3. val defaultTimeZone = DateTimeZone.forID("Asia/Shanghai")
  4. def unapply(binary: Array[Byte]): Option[Snapshot] = {
  5. val c = new BitCompress(ChannelBuffers.wrappedBuffer(ByteOrder.LITTLE_ENDIAN, binary))
  6.  
  7. val from = c.decompressString("UTF-8")
  8. val sn = c.readLong()
  9.  
  10. val dateTime = {
  11. val date = c.decompressLong().toInt
  12. val time = c.decompressLong().toInt
  13.  
  14. DateTimeFormat.forPattern("yyyyMMddHHmmssZ").withOffsetParsed().parseDateTime(
  15. f"""$date%08d$time%06d+0800"""
  16. )
  17. }
  18.  
  19. val marketId = MarketId(c.decompressLong().toInt)
  20.  
  21. //9:25 - 9:30 之间市场标志已经处于连续交易状态,但实际市场处于连续交易之前的准备阶段
  22. //特殊处理一下,将9:30之前的连续交易状态处理成集合竞价状态
  23. val marketStatus = {
  24. val cur = MarketStatus(c.decompressLong().toInt)
  25.  
  26. val before930 = dateTime.getHourOfDay == 9 &&
  27. dateTime.getMinuteOfHour < 30
  28.  
  29. val before9 = dateTime.getHourOfDay < 9
  30.  
  31. import MarketStatus._
  32. if (
  33. cur == ContinueTrade && (before930 || before9)
  34. ) {
  35. Auction
  36.  
  37. } else {
  38. cur
  39. }
  40. }
  41.  
  42. val count = c.decompressLong().toInt
  43.  
  44. val buf = new ListBuffer[SnapshotItem]
  45. for (i <- 1 to count) {
  46. val divider = if (c.decompressLong() == 4) 10000 else 1000 //价格除数
  47.  
  48. val time = new DateTime(c.readInt()*1000L, defaultTimeZone) //date time
  49.  
  50. val marketId = MarketId(c.readShort())
  51. val symbol = c.decompressString()
  52. val cnName = c.decompressString()
  53.  
  54. val prevClose = BigDecimal(c.decompressLong()) / divider
  55. val open = (BigDecimal(c.decompressLong()) / divider) + prevClose
  56. val high = (BigDecimal(c.decompressLong()) / divider) + prevClose
  57. val low = (BigDecimal(c.decompressLong()) / divider) + prevClose
  58. val close = (BigDecimal(c.decompressLong()) / divider) + prevClose
  59.  
  60. val volume = BigDecimal(c.readFloat())
  61. val amount = BigDecimal(c.readFloat())
  62.  
  63. val pe = BigDecimal(c.decompressLong()) / 100
  64.  
  65. //order books
  66. val (bids, asks) = orderBooks(c, divider)
  67.  
  68. val tradeLots = c.decompressLong() //成交笔数
  69.  
  70. val suspended = if (c.decompressLong() == 0) false else true //停牌
  71. val holds = c.decompressLong() //持仓
  72. c.decompressLong() //unused
  73.  
  74. buf += SnapshotItem(
  75. time,
  76. marketId, symbol, cnName,
  77. prevClose, open, high, low, close, volume, amount,
  78. pe, bids, asks,
  79. tradeLots, suspended, holds
  80. )
  81. }
  82.  
  83. Some(Snapshot(
  84. from,
  85. sn,
  86. dateTime,
  87. marketId, marketStatus,
  88. buf.toList
  89. ))
  90. }
  91.  
  92. /**
  93. * 优化OrderBook性能
  94. *
  95. * order book结构如下
  96. * bids: price1 ... price5 lots1 ... lots5
  97. * asks: price1 ... price5 lots1 ... lots5
  98. */
  99. @inline
  100. private def orderBooks(c: BitCompress, divider: Int) = {
  101. val base = c.decompressLong()
  102.  
  103. val bidsPrice = Array(
  104. base,
  105. c.decompressLong() + base,
  106. c.decompressLong() + base,
  107. c.decompressLong() + base,
  108. c.decompressLong() + base
  109. )
  110.  
  111. val bidsLots = Array(
  112. c.decompressLong(),
  113. c.decompressLong(),
  114. c.decompressLong(),
  115. c.decompressLong(),
  116. c.decompressLong()
  117. )
  118.  
  119. val asksPrice = Array(
  120. c.decompressLong() + base,
  121. c.decompressLong() + base,
  122. c.decompressLong() + base,
  123. c.decompressLong() + base,
  124. c.decompressLong() + base
  125. )
  126.  
  127. val asksLots = Array(
  128. c.decompressLong(),
  129. c.decompressLong(),
  130. c.decompressLong(),
  131. c.decompressLong(),
  132. c.decompressLong()
  133. )
  134.  
  135. var bids: List[OrderBook] = Nil
  136. for (i <- 0 to 4) {
  137. if (bidsPrice(i) != 0) {
  138. bids = OrderBook(
  139. BigDecimal(bidsPrice(i)) / divider,
  140. BigDecimal(bidsLots(i))
  141. ) :: bids
  142. }
  143. }
  144.  
  145. var asks: List[OrderBook] = Nil
  146. for (i <- 0 to 4) {
  147. if (asksPrice(i) != 0) {
  148. asks = OrderBook(
  149. BigDecimal(asksPrice(i)) / divider,
  150. BigDecimal(asksLots(i))
  151. ) :: asks
  152. }
  153. }
  154.  
  155. (bids.reverse, asks.reverse)
  156. }
  157. }

scala位压缩与行情转换二进制的更多相关文章

  1. Java 进制转换(二进制(负),八进制,十进制,十六进制),位运算、逻辑运算(2)

    负数的二进制表现形式:其实就是该数的绝对值取反+1. 进制转换(二进制,八进制,十进制,十六进制),原理解析 十六进制的表现形式: (2)(与.异或.左移.右移.三元运算符)

  2. Formiko总结整数十进制转换二进制原理

    引子: 为什么十进制转二进制的“辗转相除记录余数倒序输出”的算法是正确的?这个问题陪伴了Formiko半年. 实践: 实践一:把十进制数100转换成二进制数的图   上图和和下图唯一的区别在最后一位上 ...

  3. C#由转换二进制所引起的思考,了解下?

    前言 最近遇到很有意思转换二进制的问题,有部分童鞋俨然已了解,可能也有一部分童鞋没碰到过也就不知情,这里我们来深入学习下转换二进制所带来的问题. 二进制转换问题 假设现在我们有一个int类型的数据,它 ...

  4. POJ 1753. Flip Game 枚举or爆搜+位压缩,或者高斯消元法

    Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37427   Accepted: 16288 Descr ...

  5. NowCoder猜想(素数筛法+位压缩)

    在期末被各科的大作业碾压快要窒息之际,百忙之中抽空上牛客网逛了逛,无意中发现一道好题,NowCoder猜想,题意很明显,就是个简单的素数筛法,但竟然超内存了,我晕(+﹏+)~  明明有 3 万多 k ...

  6. python 调用第三方库压缩png或者转换成webp

    因为工作需要去研究了下png的压缩,发现转换成webp可以小很多,但是webp在手机上的解码速度比png的解码速度慢很多.出于进几年手机设备的处理器的性能也不错了,所以准备两套方案. 在网上搜索了一些 ...

  7. Python 进制转换 二进制 八进制 十进制 十六进制

    Python 进制转换 二进制 八进制 十进制 十六进制 作者:方倍工作室 地址:http://www.cnblogs.com/txw1958/p/python3-scale.html 全局定义一定不 ...

  8. scala 时间,时间格式转换

    scala 时间,时间格式转换 1.scala 时间格式转换(String.Long.Date) 1.1时间字符类型转Date类型 1.2Long类型转字符类型 1.3时间字符类型转Long类型 2. ...

  9. python的进制转换二进制,八进制,十六进制及其原理

    #!usr/bin/env python# coding:utf-8def binary(): '''二进制的方法与算法'''    Number = 10    Number1 = 20    Nu ...

随机推荐

  1. 微软为啥让免费升Win10?

           今天终于赶在截止日期之前把我的联想PC升到win10.微软这次对中国开放的持续一年的免费升级活动主要有两个原因.首先当然是"感恩Windows用户长久支持的回馈".微 ...

  2. Http协议详解,获取doPost,doGet提交的数据,以及编码问题

    一 什么是Http协议 http协议: 浏览器客户端 和  服务器端 之间数据传输的格式规范 二 如何查看Http协议的内容 1)使用火狐的firebug插件(右键->firebug->网 ...

  3. spring的配置文件和加载

    ①:创建applicationContext.xml配置文件放在src下 //applicationContext.xml代码 <?xml version="1.0" enc ...

  4. JAVA课程设计--简易计算器(201521123022 黄俊麟)

    1.团队课程设计博客链接 http://www.cnblogs.com/I-love-java/p/7058752.html 2.个人负责模板或任务说明 1.初始化业务逻辑. 2.开方.正负.清零.退 ...

  5. 201521123078 《Java程序设计》第十三周学习总结

    1. 本周学习总结 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同? 查询Ip地址 ...

  6. 详解go语言的array和slice 【一】

    本篇会详细讲解go语言中的array和slice,和平时开发中使用他样时需要注意的地方,以免入坑. Go语言中array是一组定长的同类型数据集合,并且是连续分配内存空间的. 声明一个数组 var a ...

  7. iOS内购 服务端票据验证及漏单引发的思考.

    因业务需要实现了APP内购处理,但在过程中出现了部分不可控的因素,导致部分用户反映有充值不成并漏单的情况. 仔细考虑了几个付费安全上的问题,凡是涉及到付费的问题都很敏感,任何一方出现损失都是不能接受的 ...

  8. 对比requirejs更好的理解seajs

    seajs遵循CMD规范,requirejs遵循AMD规范.AMD规范是预加载,CMD规范是赖加载. 下文举例假设有文件 b.js, c.js如下 //b.js define(function(req ...

  9. 深入理解计算机系统(2.5)------C语言中的有符号数和无符号数以及扩展和截断数字

    上一篇博客我们讲解了计算机中整数的表示,包括无符号编码和补码编码,以及它们之间的互相转换,个人觉得那是非常重要的知识要点.这篇博客我们将介绍C语言中的有符号数和无符号数以及扩展和截断数字. 1.C语言 ...

  10. GitHub开源:升讯威微信营销系统(第三方微信平台)完整源代码

    GitHub:https://github.com/iccb1013/Sheng.WeixinConstruction 升讯威微信营销系统开发实践系列升讯威微信营销系统开发实践:(1)功能设计与架构设 ...