Laden...

BinärDatei lesen mit festen Positionen und einem Start-"SuchText"

Erstellt von Torni vor 3 Jahren Letzter Beitrag vor 3 Jahren 433 Views
T
Torni Themenstarter:in
50 Beiträge seit 2014
vor 3 Jahren
BinärDatei lesen mit festen Positionen und einem Start-"SuchText"

Hi,

bräuchte mal ein Schubs in folgender Richtung:

Ich habe eine Datei (kein Text) in der aber an bestimmten Positionen Klartextstücke stehen.
Diese müsste ich suchen und ab da dann an festen Postionen Zahlen auslesen.

Bsp. an Position ( hex ) FF2D kommt der Suchtext "blabla" und nach diesem an Position z.B. +540 Zeichen steht das was ich auslesen muss..
Dies wird innerhalb der Datei mehrmals wiederholt immer vom gleichen Suchtext an mit gleichem Abstand wie oben genannt der auszulesende....

Wie gehe ich da am bersten vor??

2.298 Beiträge seit 2010
vor 3 Jahren

Kennst du denn die groben Bytepositionen? Dann würde ich das File einlesen und dann die entsprechenden Bytes auslesen.
Andernfalls wird es schon schwieriger, wenn du tatsächlich über bestimmte Inhaltsmuster gehen musst.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

6.911 Beiträge seit 2009
vor 3 Jahren

Hallo Torni,

der Suchtext "blabla"

Steht der Suchtext als Text od. auch binär in der Datei?

und nach diesem an Position z.B. +540 Zeichen steht das was ich auslesen muss..

Ist der Offset (hier die +540) gegeben od. wie werden diese ermittelt?
Das was du auslesen musst ist was? Ein struct od. etwas protokollbasiertes das geparst werden muss?

Ich frag deshabl, da es mit Span und MemoryMarshal ein paar sehr gute APIs für solche Fälle gibt.
Je nach Größe der Datei (wie groß ist die?) gibt es ev. mit dem SequenceReader eine weitere Alternative um das elegant und performant lesen zu können.

Aber bevor wir uns ev. in etwas verrennen beantworte bitte diese Fragen.
Am besten wäre wenn du ein Beispiel zeigen könntest wie die Datei ausschaut und was das Ergebnis sein soll.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

T
Torni Themenstarter:in
50 Beiträge seit 2014
vor 3 Jahren

Hi,

also der Suchtext steht als Plain-Text drin.
Nach dem Text steht das was ich auslesen muss in immer fixem Abstand zum Suchtext ebenfalls als Plain-Text drin.

Auslesen per BinraryReader und dann per .BaseStream.Position ... ist an für sich kein großes Problem aber eben den Suchtext zu finden schon. 😦
Ich komme da auf keinen grünen Zweig oder denke da zu verquert...

4.931 Beiträge seit 2008
vor 3 Jahren

Da wirst du wohl blockweise Daten auslesen müssen und dann den Suchtext dadrin suchen müssen (und dann jedemal Blockgröße - Länge_des_Suchtexts weiterspringen, damit der Suchtext nicht übersprungen wird).

PS: Um was für ein Dateiformat handelt es sich denn?

6.911 Beiträge seit 2009
vor 3 Jahren

Hallo Torni,

also der Suchtext steht als Plain-Text drin.

Als UTF-8 od. wie? Häng am besten so eine Beispiel-Datei an.
Wenns so ist wie ich mir vorstelle, dann lässt sich das elegant lösen -- aber bevor ich ein Demo zeige (da es doch nicht so gebräuchliche APIs sind) will ich gerne sehen wie es konkret ist, nicht dass ich was mache das den Punkt nicht trifft.

Außerdem hab ich oben noch mehr Fragen gestellt. Du willst Hilfe, also bitte ermögliche es den Helfern auch helfen zu können indem du die Fragen beantwortest.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

T
Torni Themenstarter:in
50 Beiträge seit 2014
vor 3 Jahren

Huhu gfoidl,

die Dateien haben eine Größe von ca. 80kb bis ca. 300kb - je nach Anzahl der darin enthaltenen Datensätze.

Das erste Aufkommen des Suchtextes (im Bild ersichtlich mit XSA40.... hat zum nächsten Suchtext XSA40... den gleichen Abstand.
Aber eben den ersten zu finden ist tricky...
Vom Suchtext aus lese ich mir dann die gelbmarkierte Zahlen aus..

Das ist mein Versuch wenn ich die Position des ersten Datensatzes kenne (im Hex-Edit geschaut):
(funktioniert so weit auch..)


            string st = "";
            BinaryReader br = new BinaryReader(File.OpenRead(directoryItem));
            br.BaseStream.Position = 0xEED4; //4 Zeichen für Listennummer

            while (br.BaseStream.Position < br.BaseStream.Length)
            {
                foreach (char mychar in br.ReadChars(4))
                {
                    st += mychar.ToString();
                }
                st += "=";

                br.BaseStream.Position += 0x38c; // 
                foreach (char mychar in br.ReadChars(6))
                {
                    if (mychar == 0)
                    {
                        st += "999999";//bestimmte DS haben keine Nummer vorgegeben- setze universelle
                        break; 
                    }
                    st += mychar.ToString();

                }
                st += ";";

                br.BaseStream.Position += 0x2fa;
            }
            br.Dispose();

            string[] t = st.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
           
            char[] separatorArray = { '=' }; 
            HashSet<string> dedupl = new HashSet<string>();

            var res = t
                .Select(s => s.Split(separatorArray))
                .Where(x => dedupl.Add(x[0]))
                .ToDictionary(x => x[0], x => x[1]);


p.s.: Der Typ der Datei Testdat.dat kann nicht hochgeladen werden.

6.911 Beiträge seit 2009
vor 3 Jahren

Hallo Torni,

Der Typ der Datei Testdat.dat kann nicht hochgeladen werden.

Z.B. als zip sollte gehen od. umbenennen in Testdat.txt.
Probier das einmal, dann zeig ich ein Demo wie es mit Span und Freu(n)de geht.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

T
Torni Themenstarter:in
50 Beiträge seit 2014
vor 3 Jahren

als .txt hochgeladen

6.911 Beiträge seit 2009
vor 3 Jahren

Hallo Torni,

es ist eine Binärdatei und der Text den du siehst, wird nur vom Hex-Viewer so dargestellt, da es druckbare ASCII-Zeichen sind.
Daher kann der Suchtext mit entsprechender Kodierung in die binäre Darstellung gebracht und so direkt nach diesem gesucht werden.

Die Dateigröße ist recht überschaubar, daher am einfachsten alles aufeinmal einlesen. Das erspart komplizierteren Code bei dem z.B. in einem Buffer gelesen wird (od. mit Pipelines arbeitet).

Als Anstoss -- v.a. zum Suchen des Suchtextes:


using System;
using System.IO;
using System.Text;

Encoding encoding       = Encoding.GetEncoding("iso-8859-1");   // what's the correct encoding?
const string searchText = "XSA40_DATENSATZ";

ReadOnlySpan<byte> data         = File.ReadAllBytes("Torni.dat");
ReadOnlySpan<byte> searchPhrase = encoding.GetBytes(searchText);

while (!data.IsEmpty)
{
    int index = data.IndexOf(searchPhrase);

    if (index < 0)
    {
        Console.WriteLine("Nothing found :-(");
        break;
    }

    Console.WriteLine($"First occurrance of searchText at position {index}");

    // Move behind the found searchText
    if (data.Length < searchPhrase.Length) break;

    data = data.Slice(index + searchPhrase.Length);

    if (data.Length < 3) break;

    // Move to first int-data
    data = data.Slice(3);

    string value = encoding.GetString(data.Slice(0, 4));
    Console.WriteLine($"Value found: {value}");

    // I'll break here, as it's just a demo for you ;-)
    break;
}

Dabei wird Span verwendet, da sich so das Suchen mit IndexOf trivial gestaltet. Nachdem etwas gefunden wurde, wird mit Slice die Span "zerschnitten", so dass nur mehr der Rest übrig bleibt und dieser kann weiter untersucht werden.

Ganz klar ist mir noch nicht geworden wie und wo und welche Werte gelesen werden sollen. Aber das solltest du selbst schaffen 😉
Tipp: sollten Zahlen, etc. gelesen werden, so schau dir die BinaryPrimitives-Klasse an, welche perfekt mit Span harmoniert.

BTW: warum baust du in deinem Code einen String zusammen, nur damit dieser dann wieder aufgeteilt werden muss um diesen in ein Dictionary zu stopfen? Das kannst du doch direkt ohne den String auch machen? Aber wie erwähnt, mir ist noch immer nicht ganz klar was es werden soll.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

T
Torni Themenstarter:in
50 Beiträge seit 2014
vor 3 Jahren

Hi gfoidl,

das kannte ich so noch gar nicht.
Sieht sehr interessant aus und muss ich mir mal zur Gemüte führen.

Sieht aber sehr vielversprechend aus, danke..

das mit dem zusammenbauen und wieder aufteilen waren fragmente des probierens...mus sich später ins reine schreien..

Danke dir, das hilft...

T
2.219 Beiträge seit 2008
vor 3 Jahren

Noch ein Tipp in eigener Sache und etwas Offtopic.
Wenn du Stings häufig zusammen setzen oder bearbeiten musst, dann nimm den StringBuilder aus System.Text.
Direkt mit Strings zu bearbeiten erzeugt immer neue String Instanzen.
Je mehr Operationen du auf deinem String durchführst um so mehr tote Instanzen muss die .NET Runtime verwalten und löschen.
Das ist sehr unperformant, wenn man dies sher häufig macht.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.