2011-11-23 18 views
20

tôi đang làm ứng dụng trong C#. Trong ứng dụng đó tôi có mảng byte chứa giá trị hex.Làm thế nào để có được ít dữ liệu cuối cùng từ endian lớn trong C# sử dụng phương thức bitConverter.ToInt32?

Ở đây tôi đang nhận dữ liệu như một người cuối lớn nhưng tôi muốn nó như là một người cuối cùng nhỏ.

Ở đây tôi đang sử dụng phương pháp Bitconverter.toInt32 để chuyển đổi giá trị đó thành số nguyên. Tuy nhiên, vấn đề của tôi là trước khi chuyển đổi giá trị, tôi phải sao chép dữ liệu 4 byte đó thành mảng tạm thời từ mảng byte nguồn và sau đó đảo ngược mảng byte tạm thời đó.

Tôi không thể đảo ngược mảng nguồn vì nó cũng chứa dữ liệu khác.

Do đó, đơn đăng ký của tôi trở nên chậm. mã Ở đây tôi có một mảng nguồn byte là waveData [] .Nó chứa rất nhiều dữ liệu.

byte[] tempForTimestamp=new byte[4]; 
tempForTimestamp[0] = waveData[290]; 
tempForTimestamp[1] = waveData[289]; 
tempForTimestamp[2] = waveData[288]; 
tempForTimestamp[3] = waveData[287]; 
int number = BitConverter.ToInt32(tempForTimestamp, 0); 

Có phương pháp nào khác cho chuyển đổi đó không?

Trả lời

19

Nếu bạn biết dữ liệu là lớn về cuối nhỏ, có lẽ chỉ làm điều đó bằng tay:

int value = (buffer[i++] << 24) | (buffer[i++] << 16) 
      | (buffer[i++] << 8) | buffer[i++]; 

này sẽ làm việc đáng tin cậy trên bất kỳ CPU, quá. Lưu ý i là mức bù hiện tại của bạn vào bộ đệm.

cách tiếp cận khác sẽ được xáo trộn các mảng:

byte tmp = buffer[i+3]; 
buffer[i+3] = buffer[i]; 
buffer[i] = tmp; 
tmp = buffer[i+2]; 
buffer[i+2] = buffer[i+1]; 
buffer[i+1] = tmp; 
int value = BitConverter.ToInt32(buffer, i); 
i += 4; 

tôi thấy là người đầu tiên vô cùng dễ đọc hơn, và không có chi nhánh/mã phức tạp, vì vậy nó nên làm việc khá nhanh quá. Thứ hai cũng có thể chạy vào các vấn đề trên một số nền tảng (nơi mà CPU đang chạy lớn-endian).

11

Ở đây bạn đi

public static int SwapEndianness(int value) 
    { 
     var b1 = (value >> 0) & 0xff; 
     var b2 = (value >> 8) & 0xff; 
     var b3 = (value >> 16) & 0xff; 
     var b4 = (value >> 24) & 0xff; 

     return b1 << 24 | b2 << 16 | b3 << 8 | b4 << 0; 
    } 
27

Trong thời hiện đại ngày LINQ one-liner và dễ nhất để hiểu phiên bản sẽ là:

int number = BitConverter.ToInt32(waveData.Skip(286).Take(4).Reverse().ToArray(), 0); 

Bạn cũng có thể ...

byte[] tempForTimestamp = new byte[4]; 
Array.Copy(waveData, 287, tempForTimestamp, 0, 4); 
Array.Reverse(tempForTimestamp); 
int number = BitConverter.ToInt32(tempForTimestamp); 

:)

+4

Các hình thức đầu tiên không làm việc cho tôi mà không một '.ToArray() 'sau' Đảo ngược()'. – heltonbiker

4

Khai báo lớp này:

namespace BigEndianExtension 
    { 
     public static class BigEndian 
     { 
      public static short ToBigEndian(this short value) { 
       return System.Net.IPAddress.HostToNetworkOrder(value); 
      } 
      public static int ToBigEndian(this int value) 
      { 
       return System.Net.IPAddress.HostToNetworkOrder(value); 
      } 
      public static long ToBigEndian(this long value) 
      { 
       return System.Net.IPAddress.HostToNetworkOrder(value); 
      } 
      public static short FromBigEndian(this short value) 
      { 
       return System.Net.IPAddress.NetworkToHostOrder(value); 
      } 
      public static int FromBigEndian(this int value) 
      { 
       return System.Net.IPAddress.NetworkToHostOrder(value); 
      } 
      public static long FromBigEndian(this long value) 
      { 
       return System.Net.IPAddress.NetworkToHostOrder(value); 
      } 
     } 
    } 

Ví dụ, tạo ra một hình thức với một nút và một textbox multiline:

//Some code... 
using BigEndianExtension; 
//Some code... 
private void button1_Click(object sender, EventArgs e) 
{ 
    short int16 = 0x1234; 
    int int32 = 0x12345678; 
    long int64 = 0x123456789abcdef0; 
    string text = string.Format("LE:{0:X4}\r\nBE:{1:X4}\r\n", int16, int16.ToBigEndian()); 
    text += string.Format("LE:{0:X8}\r\nBE:{1:X8}\r\n", int32, int32.ToBigEndian()); 
    text += string.Format("LE:{0:X16}\r\nBE:{1:X16}\r\n", int64, int64.ToBigEndian()); 
    textBox1.Text = text; 
} 
//Some code... 
1

Nếu bạn sẽ không bao giờ trở lại cần điều đó đảo ngược, mảng tạm thời, bạn chỉ có thể tạo ra nó như bạn vượt qua thay vì thực hiện bốn bài tập. Ví dụ:

int i = 287; 
int value = BitConverter.ToInt32({ 
    waveData(i + 3), 
    waveData(i + 2), 
    waveData(i + 1), 
    waveData(i) 
}, 0); 
0

tôi sử dụng các chức năng helper sau

public static Int16 ToInt16(byte[] data, int offset) 
    { 
     if (BitConverter.IsLittleEndian) 
     { 
      return BitConverter.ToInt16(BitConverter.IsLittleEndian ? data.Skip(offset).Take(2).Reverse().ToArray() : data, 0); 
     } 
     return BitConverter.ToInt16(data, offset); 
    } 

    public static Int32 ToInt32(byte[] data, int offset) 
    { 
     if (BitConverter.IsLittleEndian) 
     { 
      return BitConverter.ToInt32(BitConverter.IsLittleEndian ? data.Skip(offset).Take(4).Reverse().ToArray() : data, 0); 
     } 
     return BitConverter.ToInt32(data, offset); 
    } 

    public static Int64 ToInt64(byte[] data, int offset) 
    { 
     if (BitConverter.IsLittleEndian) 
     { 
      return BitConverter.ToInt64(BitConverter.IsLittleEndian ? data.Skip(offset).Take(8).Reverse().ToArray() : data, 0); 
     } 
     return BitConverter.ToInt64(data, offset); 
    } 
Các vấn đề liên quan