Entwickler-Ecke

Algorithmen, Optimierung und Assembler - Fremde Binärdatei auslesen?


Christoph1972 - Mi 13.08.14 21:59
Titel: Fremde Binärdatei auslesen?
Hallo Leute,

ich würde gerne eure Meinung hören. Und zwar habe ich eine Binärdatei von einer Messegerätesoftware. In dieser Datei sollen Laut Internet X Y Koordinaten stehen mit denen ein Chart gezeichnet wird. Dieses Chart möchte ich nun gerne in einem Programm von mir zeichnen, dazu muss ich diese Datei auslesen und genau dass ist das Problem. Dieses Vorhaben hatten auch schon andere User im Internet, eine Lösung wurde bisher nicht präsentiert. Es gibt jedoch einige Firmen die Editoren für genau diese Datei anbieten, die haben es irgendwie geschafft die Struktur der Datei aufzuklären. Ein Open Source Projekt gibt es auch, aber genau dieser Teil ist nicht frei :-)

Es ist gut möglich, das diese Datei mit .Net erzeugt wird, da es ein .Net Programm ist. Es ist aber auch möglich, das der Programmabschnitt noch eine Altlast aus den Zeit vor .Net ist. Das Programm ist an sich recht alt und wurde vor ein paar Jahren auf .Net umgestellt.

Was meint ihr, besteht eine realistische Möglichkeit die Point Liste aus der Datei zu extrahieren?


Ralf Jansen - Mi 13.08.14 22:13

Zitat:
Was meint ihr, besteht eine realistische Möglichkeit die Point Liste aus der Datei zu extrahieren?


Wenn du weißt was für Daten drin abgelegt sind klar. Du hast dann genug Anhaltpunkte nach denen man die Datei untersuchen kann. Ob dann letztlich das Reverse Enginnering einfach, schwer oder unmöglich ist weißt du erst nachher. Aber die Grundlage mit der du arbeiten kannst ist zumindest gegeben.


Christoph1972 - Mi 13.08.14 22:24

user profile iconRalf Jansen hat folgendes geschrieben Zum zitierten Posting springen:
Du hast dann genug Anhaltpunkte nach denen man die Datei untersuchen kann.


Ich habe mir die Datei mit einem Hex Editor angschaut, das hat mich aber nicht schlauer gemacht....

Wie geht man die Sache üblicherweise an? Das ist leider absolutes Neuland für mich.


ub60 - Mi 13.08.14 22:57

Hier mal einige Möglichkeiten:


ub60


Christoph1972 - Do 14.08.14 07:00

[quote="[user]Christoph1972[/user]"(688536)]
user profile iconub60 hat folgendes geschrieben Zum zitierten Posting springen:

  • Nach Möglichkeit einen der beiden oder beide Werte konstant halten.
  • Anschließend mehrfach auftauchende Byte-Folgen im Hex-Code suchen.
  • Unbedingt einige Werte aus der Messreihe aufschreiben.
  • Diese Werte in Byte, Word, Integer, Single, Double, ... unwandeln und die entstehenden Bytefolgen im Hex-Code suchen.

ub60


Ich hatte bereits nach Werten mit dem Hex Editor gesucht, leider ohne Treffer. Ich vermute das könnte an berechneten Werten liegen. Ich werde das heute noch mal angehen. Vielen Dank schon mal so weit!


Christian S. - Do 14.08.14 07:46

Man sollte auch ausprobieren, ob die Werte im Little- oder Big-Endian-Format gespeichert werden.


Nersgatt - Do 14.08.14 07:58

Stell die Datei hier ins Forum und formuliere irgend eine obskure Geschichte um die Datei, in dem Wichtel und Weihnachtsmänner vorkommen. Dann ist das Format in 1-2 Tagen geknackt... :mrgreen:


Horst_H - Do 14.08.14 09:45

Hallo,

dann schreibe Dir doch einen eigenen Datendeuter.
In dem Du Daten bei x und x+Offset anzeigen lässt:
Vertikale Memo links die Daten ab einem verschieblichem StartWert rechts ab StartWert+verschieblichem Offset.( eventuell bei Startwert +2xOffset )
In den Memos alle Varianten an Ausgaben, die Dir einfallen ,
jeweils little und big endian
Byte integer Word ,longint,long Word Int64 Double extended ,TdateTime
Dann als zum Beispiel 16 Byte als HEX -Werte
und 16 Byte als Char oder unicode ( Schreibt ein Messgerät Texte außer im Header ?? )
Das müßte doch fix gehen.

Aber user profile iconNersgatt hat recht, eine typische Wichtelmann-Frage :zustimm:

Gruß Horst


Martok - Do 14.08.14 16:55

Du könntest ja auch so mal eine Datei posten ;)

Am Besten irgendwas mit bekannten Messwerten, 0 oder so.


Christoph1972 - Do 14.08.14 17:04

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Du könntest ja auch so mal eine Datei posten ;)

Am Besten irgendwas mit bekannten Messwerten, 0 oder so.


Hi Leute,

hier ist schon mal die Datei. Messwerte kann ich erst morgen nachliefern.


jaenicke - Do 14.08.14 20:02

Ist das ein Agilent Format?


Christoph1972 - Do 14.08.14 20:06

Ja


Christoph1972 - Do 14.08.14 20:27

Bei den Werten würde Little Endian am besten passen, die Werte liegen immer um die 7.5, eigentlich sollte sie um die 10 sein. Ist aber gut möglich das da ein Faktor herangezogen wird. Die 7.5er würden gut als Y-Wert passen. Igrendie sind das aber alles Zahlen im selben Bereich, das passt nicht zu den X-Werten.....

Eine interessante Geschichte jedenfalls :-)

Vielen Dank schon mal für eure Unterstützung!


Martok - Do 14.08.14 21:06

Also angeblich sollte aus dem Gerät CDF/AIA rausfallen, das ist das aber nicht.

Bei den Werten würde ich ja auf IBM-Double tippen, da kommt man schon in die richtige Ecke (falls noch irgendwo ein Exponent abhanden gekommen ist...)


GuaAck - Do 14.08.14 21:26

Hallo,

die Datei scheint von einem HP Agilent Gaschromatografen zu stammen. Evtl. gibt es da eine Doku.

Ab $1800 sind ist die Datenreihe, m.E. little Endien, IEEE single (32 Bit) Gleitpunkt, auf 64 bit Grenze. Dann ist das eine Zahlenreihe mit Werten zwischen 7.5 und 9. Bei jeder anderen Interpretation kommen merkwürdige Zahlen raus.

Sie Dir mal "Tiny Hexer" (http://www.mirkes.de) das, das kleine Tool zeigt die Daten in einem wählbaren Format an.

Gruß GuaAck


Christoph1972 - Do 14.08.14 22:28

user profile iconGuaAck hat folgendes geschrieben Zum zitierten Posting springen:
die Datei scheint von einem HP Agilent Gaschromatografen zu stammen. Evtl. gibt es da eine Doku.


Ja genau da kommt die Datei her. Eine Doku gibt es wohl nicht, im Internet habe ich nichts gefunden, auch keine Macros mit denen ich mir helfen könnte, und in unseren Dokus steht auch nichts....

Die Werte mit 7.5 könnten die Basislinie bilden, die liegt ungefähr bei 10, ist somit nicht abwägig...


Das Tool werde ich mir morgen mal anschauen!


Martok - Fr 15.08.14 02:28

Stimmt, ihr habt Recht, das war ein Fall von Overthinking bei mir ;)

Die Daten haben trotz Double als Datentyp keine Kommastellen, sondern einen festen Faktor 1E5. Die Detektionsachse(Zeit oder Retentionsfaktor müsstest noch rausbekommen) dürfte fest skaliert sein, das kann dann ja nur eine der Werte davor sein.
user defined image
Der zweite Peak ist bei {5516,5014017}.

Was sehen wir da eigentlich? Spektrometer könnt ich sogar was raten, aber Chromatographie braucht man mit Metallen so selten...


Christoph1972 - Fr 15.08.14 06:46

Wow, das ging aber schnell! Scheinbar habe ich hier bei dem einen oder anderen schlaflose Nächte angezettelt :lol:

Was man da sieht ist ein Lösemittelgemisch, ein Benzin dürfte auch enthalten sein.

Hast Du das als Text eingelesen und die Werte gesplittet? Das habe ich gestern versucht, das passte leider noch nicht.


Martok - Fr 15.08.14 15:15

user profile iconChristoph1972 hat folgendes geschrieben Zum zitierten Posting springen:
Wow, das ging aber schnell! Scheinbar habe ich hier bei dem einen oder anderen schlaflose Nächte angezettelt :lol:
*Auf die Beitragszeit guck* Och, geht doch noch :lol:

user profile iconChristoph1972 hat folgendes geschrieben Zum zitierten Posting springen:
Hast Du das als Text eingelesen und die Werte gesplittet? Das habe ich gestern versucht, das passte leider noch nicht.
Ich hab nur einen Stream aufgemacht, nach $1800 geseekt und dann bis zum EOF Double-Werte gelesen. Die dann in eine Textdatei geworfen, das Diagramm ist daraus dann mit Pi gemalt. Wie gesagt, das sind zwar die Werte, aber die hängen noch etwas in der Luft, schon was Skalierungen angeht.


Christoph1972 - Fr 15.08.14 20:42

Also, ich habe heute "fast" den ganzen Tag versucht die Datenreihe einzulesen. (Ich habe das mit .Net File.ReadAllBytes(File) gemacht) Was ich da einlese macht bisher keinen Sinn. Hier ist jetzt schon 2* $1800 gefallen, wo habt ihr das her? Das sehe ich weder in meinem Hex Editor, noch in meinem Stream. Da ich keinen gescheiten Entry Point gefunden habe, habe ich den Stream von hinten nach vorne gelesen und dann umgekehrt. Die Byte Arrays habe ich mit der BitConverter.ToSingle(Array, 0) Methode in Double umgewandelt. Da kommen dann die Werte raus die ich mit dieser Website (http://www.scadacore.com/field-applications/miscellaneous/online-hex-converter.html) ermittelt habe (zumindest die ersten und letzten Werte der Datenreihe stimmen).

Ich vermute das beim einlesen der Daten etwas durcheinander gerät....
Die Datenreihen setzen sich ja aus vierer Reihen zusammen. Gibt es dafür fertige Methoden zum lesen?


mandras - Fr 15.08.14 21:47

Gemeint ist die Dateiposition $1800=dezimal 6144
Davor stehen nur wenige Daten, ein paar Details zur Messung im Klartext.
Erst ab der o.g. Dateiposition fangen die Meßwerte an.


Christoph1972 - Fr 15.08.14 22:14

Ah ok, das sieht in meinem Editor etwas anders aus "ox1800", ich habe immer nach dem $ Zeichen gesucht. Aber die Nummer finde ich in dem Stream doch nicht wieder!? Oder etwa doch? Gut, wenn ich sie von Ende zum Anfang einlese und die Schleife immer bei "0000 0000" verlasse solte doch das selbe raus kommen. Ich denke das ich die Daten falsch einlese und daher kommen die obskuren Zahlen. Daher meine Frage ob es eine fertige Methode zum lesen gibt, oder muss ich die Logik selbst erstellen?


GuaAck - Fr 15.08.14 22:27

Hallo Christoph,

unten ein Code, der läuft, quick-and-dirty. Zu den $1800: Das sieht man mit jedem Hex-Viewer: Vorher sieht es recht unstrukturiert aus, man sieht den Text "HP Agilent....", aber ab $1800 sind die Zeilen alle gleich strukturiert: 2 x (4 x 0, 4 x Zeichen); Die Zeichen enden immer mit E40 o.ä.


Gruß GuaAck



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
UNIT UHp_Gas;

INTERFACE

USES
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

TYPE
  TForm1 = CLASS(TForm)
    Button1: TButton;
    Memo1: TMemo;
    PROCEDURE Button1Click(Sender: TObject);
  PRIVATE
    { Private-Deklarationen }
  PUBLIC
    a: ARRAY[0..100000OF single;
    { Public-Deklarationen }
  END;

VAR
  Form1: TForm1;

IMPLEMENTATION

{$R *.dfm}

PROCEDURE TForm1.Button1Click(Sender: TObject);
VAR
  f: FILE OF single;
  i: integer;
  dummy: single;
BEGIN
  assignfile(f, 'Test88.txt');
  ReSet(f);
  FOR i := 0 TO ($1800 DIV 4) - 1 DO
    Read(f, dummy);
  i := 0;
  WHILE NOT eof(f) DO
    BEGIN
      Read(f, a[i]);
      IF (i < 20AND ((i MOD 2) = 1THEN
        Memo1.Lines.Add(floattostr(a[i]));
      i := i + 1;
    END;
  closefile(f);
  Memo1.Lines.Add(inttostr(i) + ' Werte eingelesen');

END;

END.


Christian S. - Fr 15.08.14 22:41

Und hier in C# (weil ich's schon fertig hatte, bevor ich GuaAcks Beitrag gesehen habe :D):

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
      var filename = @"d:\downloads\Test88.txt";

      var bytes = File.ReadAllBytes(filename);

      var sb = new StringBuilder();
      for(int i = 0x1800; i < bytes.Length; i+=8 ) {
        var value = BitConverter.ToDouble(bytes, i);
        sb.AppendLine(value.ToString());
      }

      File.WriteAllText(@"d:\downloads\Test88_out.txt", sb.ToString());


Christoph1972 - Sa 16.08.14 09:57

user profile iconChristian S. hat folgendes geschrieben Zum zitierten Posting springen:
Und hier in C# (weil ich's schon fertig hatte, bevor ich GuaAcks Beitrag gesehen habe :D):

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
      var filename = @"d:\downloads\Test88.txt";

      var bytes = File.ReadAllBytes(filename);

      var sb = new StringBuilder();
      for(int i = 0x1800; i < bytes.Length; i+=8 ) {
        var value = BitConverter.ToDouble(bytes, i);
        sb.AppendLine(value.ToString());
      }

      File.WriteAllText(@"d:\downloads\Test88_out.txt", sb.ToString());


Danke dir! Meine Vorgehensweise war komplett falsch. Ich habe viel zu kompliziert gedacht, jetzt wo ich sehe wie einfach man das halten kann, ist mir das schon etwas peinlich :oops:

Ich denke ich muss mir noch eine andere Lösung für den Startpunkt x01800 suchen. Dieser wird ja nicht statisch sein, oder etwa doch ?

Falls doch noch Fragen auftauchen werde ich mich wieder hier melden :P

Also, vielen Dank an alle! Ohne eure Hilfe hätte ich das nicht hinbekommen!


Christoph1972 - Mo 18.08.14 16:47

Hallo zusammen,

das Problem ist scheinbar doch nicht gelöst. Und zwar habe ich eine neue Datei, von einem anderen, aber identischem Gerät. Aus dieser Datei bekomme ich einfach keine plausiblen Werte.

Ich habe auch schon den Index hin und her geschoben, da kommt einfach nichts passendes raus. Wenn ich die alte Datei nach und nach ab 0 einlese, kann man genau erkennen ab wann die Datenreihe der Messung beginnt und die Daten machen sinn. Jetzt sieht man auch wann die Reihe beginnt, aber die Werte machen einfach keinen sinn.

Ich habe einfach keine Idee was ich da falsch mache. Wäre es möglich das ihr euch die neue Datei mal anschaut?

Anbei die Datei:


Martok - Mo 18.08.14 20:34

Jeder einzelne der Messwerte ist ein NaN [http://en.wikipedia.org/wiki/NaN] (warum merkt Tiny Hexer das eigentlich nicht?)... sicher, dass das Messgerät auch was gemessen hat?

Immerhin, mit 2 Dateien hätte man jetzt schon eine realistische Chance den Dateikopf zu untersuchen.


gehstock - Mo 18.08.14 21:32

Eventuell das hier ? https://code.google.com/p/aston/source/browse/#git%2Faston%2Fpeaks


GuaAck - Mo 18.08.14 21:52

Für mich ist Test89 ein "File of Array[0..3] of 16_bit_integer" als BIG Endian (!!), Offset ist wieder wie gehabt $1800.

Logisch, nur eine Schätzung, jedenfalls vollkommen anders als Test88.

Gruß
GuaAck


gehstock - Mo 18.08.14 22:05

Test88 R e v . C . 0 1 . 0 5 [ 3 5 ]
Test89 R e v . C . 0 1 . 0 3 [ 3 7 ]

Vieleicht hat sich mit der Firmware auch das Dateiformat geändert


Christoph1972 - Mo 18.08.14 22:19

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Jeder einzelne der Messwerte ist ein NaN [http://en.wikipedia.org/wiki/NaN] (warum merkt Tiny Hexer das eigentlich nicht?)... sicher, dass das Messgerät auch was gemessen hat?

Immerhin, mit 2 Dateien hätte man jetzt schon eine realistische Chance den Dateikopf zu untersuchen.

Also mein Hex Editor bei der Arbeit hat das auch nicht gemerkt, ich auch nicht :-)

Ich hatte mir schon extra eine neue Datei rausgesucht um sicher zu sein das ich keinen abgerochenen Lauf untersuche.


user profile icongehstock hat folgendes geschrieben Zum zitierten Posting springen:
Eventuell das hier ? https://code.google.com/p/aston/source/browse/#git%2Faston%2Fpeaks

Ich denke das hilft mir nicht wirklich weiter, aber trotzdem vielen Dank für den Link!

user profile icongehstock hat folgendes geschrieben Zum zitierten Posting springen:
Test88 R e v . C . 0 1 . 0 5 [ 3 5 ]
Test89 R e v . C . 0 1 . 0 3 [ 3 7 ]

Vieleicht hat sich mit der Firmware auch das Dateiformat geändert

Ah sehr gut, DANKE! Da hätte ich auch mal selbst drauf kommen können :wink:

Gut, wenn ich jetzt noch wüsste wie wie man da brauchbare Daten rausbekommt, könnte ich mich gut darauf einstellen. Ist gut möglich das es noch weitere Firmeware Versionen gib, wir haben 10 Geräte. Mit Updates und Neuanschaffungen könnte das ein Dauerthema für mich werden :gruebel:


Martok - Mo 18.08.14 23:41

user profile iconChristoph1972 hat folgendes geschrieben Zum zitierten Posting springen:
Ist gut möglich das es noch weitere Firmeware Versionen gib, wir haben 10 Geräte. Mit Updates und Neuanschaffungen könnte das ein Dauerthema für mich werden :gruebel:
Hm, da müssten die ja die Auswertesoftware auch ständig patchen. Mal vergleichen, vielleicht gibts ja einen Datentyp-Identifier oder sowas.

Sicher, dass das Test89 komplett war? Bei 0x1074 ist in der anderen Datei sowas wie ein Kanalbezeichner, und vorher kommt mehrfach etwas was ich für Min/Max-Werte halten würde - in dieser Datei ist das +INF und NAN.

Edit2: Och menno, ich wollte doch was ganz anderes machen :rofl:
user defined image

Ich hab mal etwas rumgebastelt, so macht das mehr Sinn, ist aber auch noch nicht komplett. Was in dem record D1..D7 und A..J heißt sind die Stellen, wo ich keine Ahnung hab was das ist. Oh, und die zweite Datei ist auch nicht wirklich lesbar, aber falls das was ich "flags" getauft hab Flags sind, steht das da vielleicht sogar drin :lol:

Einheit picoAmpere? Wär jetzt die Frage was der Detektor dort tut, aber irgendwas mit Ionisation und Leitfähigkeit ists ja, wär also nicht so unerwartet.


Christoph1972 - Di 19.08.14 06:52

Guten Morgen

Ja das mit dem patchen ist mir auch ein Dorn im Auge. Zudem muss ich ja damit rechnen, das ich die Datei irgendwann nicht mehr ausgelesen bekomme, vielleicht nicht mal mit eurer Hilfe!


Da ich mir nur zu 99% sicher bin das die Datei ok ist, werde ich noch mal eine neue raussuchen, die ich zuvor selbst auswerte.


Genau die Einheit ist pA, das Signal kommt von einem FID (Flammenionisationsdetektor).

Schade, dein Projekt kann ich mir nicht anschauen, bin C#er.


Vielen Dank für eure Unterstützung, das ist echt super!


gehstock - Di 19.08.14 09:05

Mach mal mehrere logs pro gerät das würde weiterhelfen


Christoph1972 - Di 19.08.14 23:36

Hi,


user profile icongehstock hat folgendes geschrieben Zum zitierten Posting springen:
Mach mal mehrere logs pro gerät das würde weiterhelfen


Öhm, du meinst sicher Läufe/Runs, oder Logfiles?

Also, heute hatte ich leider nur wenig Zeit. Ich habe nur raus gefunden, das es nicht an der Firmware liegt. Ein weiters Gerät hat die selbe Firmware und die Datei kann ich auswerten. Die von uns nicht auswertbaren Dateien stammen von gültigen Messungen, das hatte ich auch noch mal kontrolliert. Auch die interne Export Funktion spuckt die Daten der X,Y Punkte korrekt aus. Die ChemStation hat scheinbar keine Problem ihr Format zu lesen :suspect:

Morgen werde ich mal von allen Geräten CH Files zusammen suchen und prüfen ob es noch weitere Geräte gibt die nicht gelesen werden können.


Christoph1972 - Mi 20.08.14 20:16

Heute habe ich mir eine Demo Version runtergeladen und installiert. Diese hat kein Problem die Dateien einzulesen und es wird alles korrekt gezeichnet. Es muss also ein Trick geben. Hat vielleicht noch jemand eine weitere Idee?


C# - Do 21.08.14 00:17

ALso ich bin kein Profi :mrgreen: aber hast du schon versucht die Demo zu dekompilieren? Dann könntest du dort nach der Formatierung schauen.