2011-01-07 69 views
1

我需要用舊的內部開發的算法來壓縮/解壓縮一些數據。 在那裏,我有很多類似的操作:Scala中的比特流庫

if the next bit is 0 take the following 6 Bits and interpret them as an Int 
if the next bits are 10 take the following 9 Bits and interpret them as an Int 
etc. 

有人誰知像Scala中的一個「Bitstrem」類? (我沒有發現任何東西,希望我沒有通過自己來實現它。)

感謝

編輯: 我結合http://www.scala-lang.org/node/8413答案(「Scala集合的建築」)。如果有人需要samething:

abstract class Bit 
object Bit { 
    val fromInt: Int => Bit = Array(Low, High) 
    val toInt: Bit => Int = Map(Low -> 0, High -> 1) 
} 

case object High extends Bit 
case object Low extends Bit 

import collection.IndexedSeqLike 
import collection.mutable.{Builder, ArrayBuffer} 
import collection.generic.CanBuildFrom 
import collection.IndexedSeq 

// IndexedSeqLike implements all concrete methods of IndexedSeq 
// with newBuilder. (methods like take, filter, drop) 
final class BitSeq private (val bits: Array[Int], val length: Int) 
     extends IndexedSeq[Bit] 
     with IndexedSeqLike[Bit, BitSeq] 
{ 
    import BitSeq._ 

    // Mandatory for IndexedSeqLike 
    override protected[this] def newBuilder: Builder[Bit, BitSeq] = 
    BitSeq.newBuilder 

    //Mandatory for IndexedSeq 
    def apply(idx: Int): Bit = { 
    if(idx < 0 || length <= idx) 
     throw new IndexOutOfBoundsException 
    Bit.fromInt(bits(idx/N) >> (idx % N) & M) 
    } 


} 

object BitSeq { 

    // Bits per Int 
    private val N = 32 

    // Bitmask to isolate a bit 
    private val M = 0x01 


    def fromSeq(buf: Seq[Bit]): BitSeq = { 
    val bits = new Array[Int]((buf.length + N - 1)/N) 
    for(i <- 0 until buf.length) { 
     bits(i/N) |= Bit.toInt(buf(i)) << (i % N) 
    } 
    new BitSeq(bits, buf.length) 
    } 

    def apply(bits: Bit*) = fromSeq(bits) 

    def newBuilder: Builder[Bit, BitSeq] = new ArrayBuffer mapResult fromSeq 

    // Needed for map etc. (BitSeq map {:Bit} should return a BitSeq) 
    implicit def canBuilderFrom: CanBuildFrom[BitSeq, Bit, BitSeq] = 
    new CanBuildFrom[BitSeq, Bit, BitSeq] { 
     def apply(): Builder[Bit, BitSeq] = newBuilder 
     def apply(from: BitSeq): Builder[Bit, BitSeq] = newBuilder 
    } 
} 

回答

4

沒有任何現有的類,我所知道的,但你可以利用現有的課程,以幫助幾乎所有困難的操作。訣竅是將數據轉換爲Ints流(如果內存不足,則爲Bytes)。然後,您可以使用所有便捷的收集方法(例如,take),只留下將位轉存到內存的問題。但是,如果你按MSB順序打包這些數據,這很容易。

object BitExample { 
    def bitInt(ii: Iterator[Int]): Int = (0 /: ii)((i,b) => (i<<1)|b) 
    def bitInt(ii: Iterable[Int]): Int = bitInt(ii.iterator) 

    class ArrayBits(bytes: Array[Byte]) extends Iterator[Int] { 
    private[this] var buffer = 0 
    private[this] var index,shift = -1 
    def hasNext = (shift > 0) || (index+1 < bytes.length) 
    def next = { 
     if (shift <= 0) { 
     index += 1 
     buffer = bytes(index) & 0xFF 
     shift = 7 
     } 
     else shift -= 1 
     (buffer >> shift) & 0x1 
    } 
    } 
} 

然後你不喜歡的東西

import BitExample._ 
val compressed = new ArrayBits(Array[Byte](14,29,126)).toStream 
val headless = compressed.dropWhile(_ == 0) 
val (test,rest) = headless.splitAt(3) 
if (bitInt(test) > 4) println(bitInt(rest.take(6))) 

(你可以決定是否要直接或流,列表,或任何使用迭代器)。

+0

感謝。但是我有一些問題需要理解:「(0 /:ii)((i,b)=>(i << 1)| b)」Specialy the「(0 /:ii)」。 /:是foldLeft。所以這將轉化爲「(0.foldLeft(ii))」? (我的mystake在哪裏?) – Fabian 2011-01-07 16:02:14