Posts mit dem Label Encoding werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Encoding werden angezeigt. Alle Posts anzeigen

Mittwoch, 29. Oktober 2008

Hexadezimaldarstellung eines Strings nach Int32 umrechnen

BBo hat mir eine Aufgabenstellung hingeworfen und wir haben diese dann unterschiedlich gelöst. Es ging darum die Hexadezimaldarstellung eines 2 Byte langen String nach Int32 zu konvertieren. Das war etwas schwieriger als wir dachten. Hier nun meine Lösungsvariante, vielleicht postet BBo ja noch seine ;)

Das Erste was mir durch den Kopf ging ist, dass dies etwas gefährlich ist in Bezug auf das Stringencoding. Denn je nach dem wie der String decodiert wurde, hat man ja je nach Umgebung eine andere Hexadezimalwertdarstellung nach dem Encodieren. Darum habe ich einfach zur Absicherung das Encoding mit eingebaut in meine Lösung. Theoretisch kann man in einer homogenen Welt darauf verzichten, doch meine praktischen Erfahrungen in den letzten Monaten haben mir oft genug die Finger verkokelt. Man kann ja selber mal damit herumspielen und mit unterschiedlichen Encodings die unterschiedlichen Ergebnisse vergleichen...

   1:  // test
   2:  int erg = TwoByteStringHexValueToInt32("Aÿ", System.Text.Encoding.GetEncoding(1252));
   3:  ...
   4:   
   5:  public static int TwoByteStringHexValueToInt32(string input, Encoding encoding)
   6:  {
   7:     if (input.Length != 2)
   8:        throw new ArgumentException("TwoByteStringHexValueToInt32 - parameter input is allowed to be 2 byte long only!");
   9:              
  10:     if (encoding == null)
  11:        encoding = System.Text.Encoding.Default;
  12:   
  13:     int result = 0;
  14:     byte[] ba = encoding.GetBytes(input); // split to byte array of 2
  15:   
  16:     if (System.BitConverter.IsLittleEndian) // when little endian we need to do a workaround
  17:     {
  18:        result = (Convert.ToInt32(ba[0]) << 8) + Convert.ToInt32(ba[1]);
  19:     }
  20:     else
  21:     {
  22:        result = (int)System.BitConverter.ToInt16(ba, 0);
  23:     }
  24:   
  25:     return result;
  26:  }

In Zeile 14 geht es richtig los, da zerleg ich den Input string in ein 2-Byte Array in Abhängigkeit (!) vom Encoding des Strings. 1252 ist das herkömmliche Encoding unter Windows für lateinische Schriftsysteme, u.a. Deutsch. Danach steht also in unserem Byte Array die Hexdarstellung unseres Strings.

Danach mache ich einen kleinen Kunstgriff in Zeile 16, x86 Syteme sind LittleEndian kodiert, Motorola z.B. normalerweise BigEndian. Hier eine kleine Info wenn man damit nichts anfangen kann. Im Klartext, normalerweise rechnet man den Wert in unserem Bytearray wie in Zeile 22 gezeigt um. Mit dem Bitkonverter nach 16Bit Integer, werden 2 Bytes aus dem Bytearray ab der Position 0 gelesen und in Integer umgerechnet (Int32 bräuchte 4 Bytes, darum dieser Umweg).

Und GENAU hier schlägt die Sache mit dem Little/Big Endian System zu! Denn wir haben zuvor oben unseren String eigentlich verkehrt herum abgelegt für unser x86 System!! Denn das rechnet von Hinten nach Vorne Bytedarstellungen nach Integer um!

Daher das Byteshifting in Zeile 18, falls ein Little Endian System vorliegt. Ich greife mir das erste Byte konvertiere es nach Int32 und verschiebe es mal 8 Bits nach "links" (= 1 Byte, wir haben ja 2 Bytes und schieben das Erste sozusagen nach "vorne"), um dann einfach das Ergebnis aus der zweiten Byte Konvertierung dazu addieren.

Nachtrag: Der Rückweg

   1:  public static byte[] Int16ToBigEndianByteArray(short input)
   2:  {
   3:     int higher = input >> 8;     // shift 1 byte -> get higher byte
   4:     int lower  = input & 0x00ff; // mask -> get lower byte
   5:   
   6:     byte[] ba = new byte[2];
   7:     ba[0] = Convert.ToByte(higher);
   8:     ba[1] = Convert.ToByte(lower);
   9:   
  10:     return ba;
  11:  }
  12:   
  13:   
  14:  ...
  15:  // test
  16:  byte[] ba = Int16ToBigEndianByteArray((short)31910);
  17:  string res = System.Text.Encoding.GetEncoding(1252).GetString(ba);

Donnerstag, 7. August 2008

Kenne deine .NET Werkzeuge - HttpUtility Class

Ich denke eines der größten individuellen Mankos ist, dass man (ich) nicht sein Framework und die damit zur Verfügung gestellten Werkzeuge kennt. Ich vermute mal ein ASP.NET Entwickler wird die HttpUtility Class (http://msdn.microsoft.com/en-us/library/system.web.httputility(VS.80).aspx) kennen, ich kannte sie nicht. Es war unerlässlich das ich ein XML von Hand zusammenkleben mußte und mein LoadXML in ein XmlDocument schlug grandios fehl. Das Problem war schnell gefunden im XML Editior von Visual Studio, der hat mir einen Eintrag rot unterringelt der ein & enthielt. Ich wollte schon loslegen eine Hilfsklasse zu schreiben die mir meine Values &, ä, ö, ü, <, > usw. konvertiert nach &amp; etc. ... Doch "Halt!", meinte mein Kollege, da muss es doch was im Framework schon geben. Nach etwas "googeln" fand ich dann die HttpUtility Class. Und die hat eine HtmlEncode Methode die einem das wunderbar erschlägt :)

string encodedValue = System.Web.HttpUtility.HtmlEncode(unencodedValue);

Das Ganze funktioniert auch innerhalb von Biztalk. Die System.Web dll muss hier explizit referenziert werden, das dürfte vermutlich auch für alle Nicht-ASP.NET Projekte gelten.