2016-03-25 26 views
1

TBytes'ten rastgele sayı bitlerini okumakla ilgili problemle karşılaştım. Öncelikle bu sorudan bir tavsiye aldım (ubitstream.pas ünitesini kullanma hakkındaki cevap): Handling arbitrary bit length data in Delphi? Benim örneğim: binaryfeed (TBytes) = (255, 0, 0, 0, 0, 6, 132, 1, 112) 128, 128, 130, 81);Delphi: TBitlerden X bitleri nasıl okunur?

  1. 8 bit okuyorum ve 255 olsun - tamam. Konum 8'dir.
  2. 24 bit okurum ve 0 - ok aldım. Pozisyon Sanırım nedenini anlayabileceği 0000 0000 0000 0110

    başka 24 bit okuyup pozisyonu 56.

393216 olduğunu 393216 yerine 6'nın almak 32.

  • olduğunu Ancak bu ekstra sıfır bitlerin nasıl kırpılacağını anlayamıyorum. Herhangi bir fikir?

  • +0

    Bu "rasgele sayı bitleri", her zaman 8 bitlik bir kat mıdır? Eğer öyleyse, bayt okuyabilirsiniz. Bu büyük-endian ise, birden çok bayt tamsayılara benzer bir şeyle birleştirilir: 'value: = nextByte + value * 256; numBits: = numBits - 8; 'sayısı bitene kadar art arda. –

    +0

    Gerçekten aradığınız 'bit access' ise (ki öyle görünmüyor, bkz. @ DavidHeffernan'ın cevabı), Delphi'nin System.Class sınıfındaki TBits sınıfına bir göz atmalısınız. –

    cevap

    7

    Sorun, endianness.

    00000110 00000000 00000000 
    

    üç bayt Ters 393216. olduğunu ve 6.

    kullandığınız kod küçük sonlu olduğunu

    00000000 00000000 00000110 
    

    var, ama büyük endian davranış için umut ediyor . Bu uyumsuzluğu hesaba katmak için kodunuzu değiştirmeniz gerekecektir.

    Yine de soruda gördüklerimizden, her zaman baytları okuyorsunuz ve kullandığınız kodun karmaşıklığına ihtiyaç duymuyorsunuz. Bayt seviyesinde çalışabilirsiniz. Açıkçası, endiantasyonu doğru bir şekilde hesaba katmanız gerekecek ama bu çok zor değil.

    +0

    >> Soruda gördüklerimizden, her zaman baytları okuyorsunuz ve kullandığınız kodun karmaşıklığına ihtiyaç duymuyorsunuz. Örneğin 3 biti okumayı desteklemem gerekiyor. – Maxim

    +0

    Tamam, sorudan net değildi, çünkü her zaman 8'in katları halinde bit okuyorsunuz. Bu nokta, endianness'ın konu olduğudur. –

    0

    İlk önce kabınızı düşünün. Eğer baytları 32bit'lik bir tam sayıya okursanız, bitleri yerine taşımak için shr/shl kullanmalısınız. , 32bit aralığından kurtulmak istemediğiniz en soldaki bitleri kopyalamak için nadir değildir, daha sonra baytları (veya ihtiyacınız olan herhangi bir büyüklükte veya boyutta) elde etmek için diğer X pozisyonlarını bırakın.

    var 
        value: integer; 
    begin 
        value := (Readint32FromBuffer shl 8) shr 8; 
        writeln(value.tostring); 
    end; 
    

    Yukarıdaki kodda, ilk 8 bit biz 8 bit o zamanlar, sola bütün şeyi 8 bit kayması öylesine dahil edilecek istemiyorum. Bu, kabın "kenarından" hareket ettiğinde bitleri sıfırlar.

    Değişken (ler) inizin içindeki bit/baytları hareket ettirmek için SHL ve SHR düğmelerini kullanın. Ama kabın büyüklüğünü hatırla. Word (16 bit), Tamsayı (32 bit) vb.

    Ayrıca, SHL ve SHR tipik olarak bir CPU yazıcısıyla aynı boyutta olan değişkenler için daha hızlı olsa da, AND ve OR maskelerinden bazılarını da elde etmek için kullanabilirsiniz. 32 bit veya 64 bit).