2012-08-16 36 views
5

Tôi đã được đọc SWF format sẵn trên trang web của Adobe và nó đề cập rằng để tiết kiệm không gian, bit biến được sử dụng để nguyên cửa hàng hoặc phao nổi (trang 17 trong pdf)bit dữ liệu canh Reading

Tôi có luôn làm việc với dữ liệu được liên kết byte, do đó, không đưa ra nhiều suy nghĩ cho các tệp được căn chỉnh bit hoặc có căn chỉnh biến nơi thông tin được lưu trữ trong mỗi byte. Ví dụ, bạn có thể có một cấu trúc chứa bốn số nguyên 13 bit được lưu trữ tuần tự (thay vì lưu chúng dưới dạng bốn số nguyên 16 bit). Ví dụ:

13 bit đầu tiên là số nguyên đầu tiên, 13 bit tiếp theo là số nguyên thứ hai, v.v. Nó đệm byte cuối cùng thích hợp để làm cho cấu trúc byte liên kết với phần còn lại của tệp, vì vậy 52 bit sẽ được đệm thành 56 bit, yêu cầu 7 byte để lưu trữ bốn số nguyên đó trái ngược với 8 byte.

  • Làm cách nào để tiếp cận loại sự cố này?
  • Làm cách nào tôi có thể làm việc với luồng byte ở cấp bit?
  • Có điều gì tôi có thể sử dụng để giúp làm việc với dữ liệu này dễ dàng hơn không?

Tôi tưởng tượng giải pháp sẽ giảm xuống bằng cách sử dụng các phép toán bit trên mảng byte.

Một giải pháp ví dụ để phân tích cú pháp bốn số nguyên 13 bit sẽ là tốt đẹp để chứng minh việc sử dụng phương pháp được đề xuất của bạn.

+0

..bởi vì tôi không thể cung cấp cho bạn câu trả lời đầy đủ, có lẽ ít nhất chỉ bạn vào 'BitArray' sẽ giúp :) –

+1

Thông thường, cách tiếp cận là giữ một bộ đệm bit trong uint hoặc ulong, trích xuất những gì bạn cần và chuyển đổi trong một byte đầu vào mới khi không có đủ bit trong bộ đệm. – harold

Trả lời

3

Có hai cách để giải quyết vấn đề này mà tôi biết. Đầu tiên là tự làm điều đó - bằng cách sử dụng các toán tử bit, phân chia, mô đun, vv trên mảng byte [hoặc số nguyên/ulong, vv nếu bạn chán]. IsBitSet Example

Một cách khác là một BitArray - mà xử lý hầu hết việc này cho bạn :)


Nó sẽ được tốt đẹp để thêm một ví dụ về cách chính xác BitArray handle nhận bit 13..25 như một int, vì đó sẽ là hoạt động chính. Thoạt nhìn tôi chỉ thấy một vòng lặp.

Fine ... Tôi đã viết một cách nhanh chóng & bằng chứng bẩn thử nghiệm của khái niệm:

var rnd = new Random(); 
//var data = Enumerable.Range(0, 10).ToArray(); 
var data = Enumerable.Range(0, 10).Select(x => rnd.Next(1 << 13)).ToArray(); 

foreach (var n in data) Console.WriteLine(n); 

Console.WriteLine(new string('-', 13)); 

var bits = new BitArray(data.Length * 13); 

for (int i = 0; i < data.Length; i++) 
{ 
    var intBits = new BitArray(new[] { data[i] }); 
    for (int b = 12; b > -1; b--) 
    { 
     bits[i * 13 + b] = intBits[b]; 
     Console.Write(intBits[b] ? 1 : 0); 
    } 
    Console.WriteLine(); 
} 
Console.WriteLine(new string('-', 13)); 

for (int i = 0; i < bits.Length/13; i++) 
{ 
    int number = 0; 
    for (int b = 12; b > -1; b--) 
     if (bits[i * 13 + b]) 
      number += 1 << b; 

    Console.WriteLine(number); 
} 
Console.ReadLine(); 

Những kết quả đầu ra:

910 
3934 
7326 
7990 
7712 
1178 
6380 
3460 
5113 
7489 
------------- 
0001110001110 
0111101011110 
1110010011110 
1111100110110 
1111000100000 
0010010011010 
1100011101100 
0110110000100 
1001111111001 
1110101000001 
------------- 
910 
3934 
7326 
7990 
7712 
1178 
6380 
3460 
5113 
7489 

Mảng chút không làm được gì nhiều ngoại trừ đơn giản hóa việc truy cập - nó vẫn khá thủ công.Tôi hy vọng bạn muốn viết các lớp học của riêng bạn để đơn giản này và làm cho nó gọn gàng và tái sử dụng - ví dụ, đây là một khái niệm nhanh chóng:

//Improved to take sign into account. 
//Sign is in addition to bits allocated for storage in this version. 
//Stored as {sign}{bits} 
//E.g. -5, stored in 3 bits signed is: 
//  1 101 
//E.g. 5, stored in 3 bits [with sign turned on] 
//  0 101 
//E.g. 5, stored in 3 bits no sign 
//   101 
//This may differ from your exiting format - e.g. you may use two's compliments. 
static void Main(string[] args) 
{ 
    int bitsPerInt = 13; 

    //Create your data 
    var rnd = new Random(); 
    //var data = Enumerable.Range(-5, 10).ToArray(); 
    var data = Enumerable.Range(0, 10).Select(x => rnd.Next(-(1 << bitsPerInt), 1 << bitsPerInt)).ToArray(); 

    var bits = new BitSerlializer(); 

    //Add length header 
    bits.AddInt(data.Length, 8, false); 
    foreach (var n in data) 
    { 
     bits.AddInt(n, bitsPerInt); 
     Console.WriteLine(n); 
    } 

    //Serialize to bytes for network transfer etc. 
    var bytes = bits.ToBytes(); 

    Console.WriteLine(new string('-', 10)); 
    foreach (var b in bytes) Console.WriteLine(Convert.ToString(b, 2).PadLeft(8, '0')); 
    Console.WriteLine(new string('-', 10)); 

    //Deserialize 
    bits = new BitSerlializer(bytes); 
    //Get Length Header 
    var count = bits.ReadInt(8, false); 
    for (int i = 0; i < count; i++) 
     Console.WriteLine(bits.ReadInt(bitsPerInt)); 

    Console.ReadLine(); 
} 

public class BitSerlializer 
{ 
    List<byte> bytes; 
    int Position { get; set; } 

    public BitSerlializer(byte[] initialData = null) 
    { 
     if (initialData == null) 
      bytes = new List<byte>(); 
     else 
      bytes = new List<byte>(initialData); 
    } 

    public byte[] ToBytes() { return bytes.ToArray(); } 

    public void Addbit(bool val) 
    { 
     if (Position % 8 == 0) bytes.Add(0); 
     if (val) bytes[Position/8] += (byte)(128 >> (Position % 8)); 
     Position++; 
    } 

    public void AddInt(int i, int length, bool isSigned = true) 
    { 
     if (isSigned) Addbit(i < 0); 
     if (i < 0) i = -i; 

     for (int pos = --length; pos >= 0; pos--) 
     { 
      var val = (i & (1 << pos)) != 0; 
      Addbit(val); 
     } 
    } 

    public bool ReadBit() 
    { 
     var val = (bytes[Position/8] & (128 >> (Position % 8))) != 0; 
     ++Position; 
     return val; 
    } 

    public int ReadInt(int length, bool isSigned = true) 
    { 
     var val = 0; 
     var sign = isSigned && ReadBit() ? -1 : 1; 

     for (int pos = --length; pos >= 0; pos--) 
      if (ReadBit()) 
       val += 1 << pos; 

     return val * sign; 
    } 
} 
+0

Sẽ rất thú vị khi thêm một ví dụ về cách xử lý BitArray chính xác nhận bit 13..25 như một int, vì đó sẽ là hoạt động chính. Thoạt nhìn tôi chỉ thấy một vòng lặp. –

+0

Whoa! Tôi rất ấn tượng. Tôi tin rằng điều này không giải quyết các dấu hiệu và phần mở rộng của nó, cũng không chắc chắn nếu hiệu suất cũng được xem xét - Keikoku đã không đề cập đến nó, vì vậy có lẽ không. Nếu không, một ví dụ tuyệt vời của một câu trả lời mở rộng. Đó là +1. –

+0

@EugeneRyabtsev - tốt bắt, được thêm vào trong các dấu hiệu trong phiên bản thứ hai của tôi. – NPSF3000

3

Mặt khác, cách tiếp cận byte mảng dựa trên có thể đi như thế này:

int extend(uint raw, int bits) 
    { 
     int sh = 32 - bits; 
     int x = (int)raw << sh; // puts your sign bit in the highest bit. 
     return x >> sh; // since x is signed this is an arithmatic signed shift 
    } 

    int read(byte[] data, int pos, int bits, bool signed) 
    { 
     int fbi = pos/8; // first byte index 
     int lbi = (pos + bits - 1)/8; // last byte index 
     int cnt = lbi - fbi + 1; // bytes spanned 
     if (cnt > 3 || lbi >= data.Length) { throw new ArgumentException(); } 

     uint raw = (uint)(
      (data[fbi] << (24 + pos % 8)) + 
      (cnt < 2 ? 0 : data[fbi + 1] << (16 + pos % 8)) + 
      (cnt < 3 ? 0 : data[fbi + 2] << (8 + pos % 8)) 
      ) >> (32 - bits); 
     return signed ? extend(raw, bits) : (int)raw; 
    } 

thử nghiệm cho việc này:

byte[] test = { 0x55, 0xAA, 0x10 }; 

    string s = ""; 
    s += read(test, 0, 8, false) + "\r\n"; 
    s += read(test, 0, 8, true) + "\r\n"; 
    s += read(test, 8, 8, false) + "\r\n"; 
    s += read(test, 8, 8, true) + "\r\n"; 
    s += read(test, 4, 8, false) + "\r\n"; 
    s += read(test, 7, 9, true) + "\r\n"; 
    s += read(test, 7, 10, true) + "\r\n"; 
    s += read(test, 7, 11, true) + "\r\n"; 
    s += read(test, 7, 12, true) + "\r\n"; 
    s += read(test, 7, 13, true) + "\r\n"; 
    s += read(test, 7, 14, true) + "\r\n"; 
    s += read(test, 7, 15, true) + "\r\n"; 
    s += read(test, 7, 16, true) + "\r\n"; 
    s += read(test, 7, 17, true) + "\r\n"; 
    s += read(test, 18, 2, true) + "\r\n"; 
    s += read(test, 18, 3, true) + "\r\n"; 
    s += read(test, 23, 1, true) + "\r\n"; 
    s += read(test, 23, 2, true) + "\r\n"; 

thử nghiệm xây dựng chuỗi như sau:

85 
    85 
    170 
    -86 
    90 
    -86 
    -172 
    -344 
    -688 
    -1375 
    -2750 
    -5500 
    -11000 
    -22000 
    1 
    2 
    0 

sau đó ném ngoại lệ trên dòng cuối cùng.

+0

Hệ thống thú vị. Thiếu khả năng ghi ... và nên được khái quát hóa để xử lý các chuỗi bit dài tùy ý [vì vậy bạn có thể dễ dàng viết các hàm để tuần tự hóa nhiều hơn int's]. – NPSF3000

Các vấn đề liên quan