1. 程式人生 > >iOS/MacOS中二進位制資料的處理

iOS/MacOS中二進位制資料的處理

文章目錄

iOS/MacOS中二進位制資料的處理

何為大小端模式?

在處理二進位制資料的時候,首先要注意區分使用大端模式(Big-endian)還是小端模式(Little-endian),何為大小端模式呢?

大端模式:是指資料的低位儲存在記憶體的高地址中,而資料的高位,儲存在記憶體的低地址中;

小端模式:是指資料的低位儲存在記憶體的低地址中,而資料的高位儲存在記憶體的高地址中。

為何有大小端之分?

在計算機系統中,我們以位元組為單位,每個地址單元都對應著一個位元組,一個位元組為8bit。但是在C語言中除了8bit的char之外,還有16bit的short型,32bit的long型(根據編譯器決定),另外,對於位數大於8位的處理器,例如16位或者32位的處理器,由於暫存器寬度大於一個位元組,那麼必然存在如何將多個位元組安排的問題。因此就導致了大端儲存模式和小端儲存模式。例如一個16bit的short型x,在記憶體中的地址為0x0010,x的值為0x1122,那麼0x11為高位元組,0x22為低位元組。對於大端模式,就將0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。即資料的低位儲存在記憶體的高地址中,而資料高位儲存在記憶體的低地址中。小端模式剛好相反,將0x22放在低地址0x0010中,0x11放在高地址0x0011中,即資料低位儲存在記憶體的低位地址中,資料的高位儲存在記憶體的高位中。我們常用的X86結構是小端模式,而KEIL C51則為大端模式。很多的ARM,DSP都為小端模式。有些ARM處理器還可以由硬體來選擇是大端模式還是小端模式。

判斷大小端

//判斷裝置是否是小端模式
- (int) isLittleEndian
{
    int i = 0x12345678;
    char *c = &i;
    return ((c[0] == 0x78) && (c[1] == 0x56) && (c[2] == 0x34) && (c[3] == 0x12));
}

NSString轉Data

/** NSString轉NSData */
- (NSData *)dataWithString:(NSString *)string {
    const char *constStr = [string UTF8String];
    return [NSData dataWithBytes:constStr length:strlen(constStr)];
}

Data轉NSString

NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

int轉Data

int i = 1;
NSData *data = [NSData dataWithBytes:&i length:sizeof(i)];

Data轉int

int y;
[data getBytes:&y length:sizeof(y)];

有時我們需要將int型別轉為bytes以方便二進位制資料的處理,例如替換二進位制指定位的資料時需要使用bytes,因此,需要將int轉為bytes

int轉bytes

//int型別轉bytes, 結果為大端模式,預設生成4位
- (void)intToBigBytes:(int)intValue bytes:(Byte *)buffer {
    for (int i = 0; i < 4; i++) {
        buffer[i] = (Byte)(intValue >> (24-i*8));
    }
}

//int型別轉bytes, 結果為小端模式,預設生成4位
- (void)intToLittleBytes:(int)intValue bytes:(Byte *)buffer {
    for (int i = 3; i >= 0; i--) {
        buffer[i] = (Byte)(intValue >> (24-i*8));
    }
}

bytes轉int

//將小端模式下的bytes轉換為int
-(int) lBytesToInt:(Byte*) byte length:(NSUInteger)length {
    if (byte == NULL) {
        return 0;
    }
    int height = 0;
    for (int i = 0; i < length; i++) {
        if (byte[length-i] >= 0) {
            height = height + byte[length-i];
        } else {
            height = height + 256 + byte[length-i];
        }
        height = height * 256;
    }
    if (byte[0] >= 0) {
        height = height + byte[0];
    } else {
        height = height + 256 + byte[0];
    }
    return height;
}

//將大端模式下的bytes轉換為int
- (int)heightBytesToInt:(Byte *)byte length:(NSUInteger)length {
    int height = 0;
    for (int i = 0; i < length; i++) {
        if (byte[i] >= 0) {
            height = height + byte[i];
        } else {
            height = height +256 + byte[i];
        }
        height = height * 256;
        if (length >= 3) {
            if (byte[3] >= 0) {
                height = height + byte[3];
            } else {
                height = height + 256 + byte[3];
            }
        }
    }
    return height;
}

其餘資料型別與NSData之間的轉換在此不再一一列出,以上部分鑑於個人在專案中使用到,總結以便掌握。