tomhake1
3 Beiträge
schrieb am 17.08.15 um 10:18 Uhr
Link zu diesem Post
Hallo zusammen,

ist es möglich die URL eines manuell hinzugefügten Streams zu ändern? Im Programm (übrigens ein riesiges Lob und Dankeschön hierfür!) habe ich keine Option gefunden.

Ein Workaround, den ich versucht habe, ist die streamwriter_data.dat zu dekomprimieren, die notwendigen Anpassungen vorzunehmen und danach wieder zu komprimieren. Ich kann zwar erfolgreich dekomprimieren, nur leider ist die Datei mit NUL characters (\x00) aufgebläht (und die Dekomprimierung funktioniert nur, nachdem ich die ersten 9 Bytes entferne oder diese mit dem gzip-Header ersetze).

Bevor wir zu tief einsteigen: Gibt es eine einfachere Möglichkeit die URLs der Streams zu ändern? Oder alternativ, alex, kannst du mir bitte verraten, mit welchen zlib-Einstellungen die streamwriter_data.dat dekomprimiert/komprimiert werden soll und was es noch zu beachten gibt?

Vielen Dank für eure Hilfe.
Tom
 
alex
2440 Beiträge
schrieb am 17.08.15 um 20:20 Uhrzuletzt bearbeitet von alex am 17.08.15 um 20:23 Uhr
Link zu diesem Post
Moin,

das passt so, wie du sagst. Das Teil ist mit zlib komprimiert und zwar als Stream direkt, nicht als Archiv mit Dateien da drin. So kann ich das Teil unter Linux auspacken (man verzeihe mir die mangelhafte Formatierung..):

alex@kreios:/tmp > dd if=streamwriter_data.dat of=modified.dat skip=1 bs=9
153032+1 Datensätze ein
153032+1 Datensätze aus
1377289 Bytes (1,4 MB) kopiert, 0,132857 s, 10,4 MB/s
alex@kreios:/tmp > cat modified.dat | zlib-flate -uncompress > decompressed.dat
alex@kreios:/tmp > hexdump -C -n 256 decompressed.dat
00000000 22 ee 11 2c 18 09 00 00 3a 29 09 00 00 00 00 00 |"..,….:)……|
00000010 00 00 00 00 3e 00 00 00 25 00 73 00 74 00 72 00 |….>…%.s.t.r.|
00000020 65 00 61 00 6d 00 6e 00 61 00 6d 00 65 00 25 00 |e.a.m.n.a.m.e.%.|
00000030 5c 00 25 00 61 00 72 00 74 00 69 00 73 00 74 00 |\.%.a.r.t.i.s.t.|
00000040 25 00 20 00 2d 00 20 00 25 00 74 00 69 00 74 00 |%. .-. .%.t.i.t.|
00000050 6c 00 65 00 25 00 42 00 00 00 25 00 73 00 74 00 |l.e.%.B…%.s.t.|
00000060 72 00 65 00 61 00 6d 00 6e 00 61 00 6d 00 65 00 |r.e.a.m.n.a.m.e.|
00000070 25 00 5c 00 25 00 61 00 72 00 74 00 69 00 73 00 |%.\.%.a.r.t.i.s.|
00000080 74 00 25 00 20 00 2d 00 20 00 25 00 74 00 69 00 |t.%. .-. .%.t.i.|
00000090 74 00 6c 00 65 00 25 00 2d 00 2d 00 32 00 00 00 |t.l.e.%.-.-.2…|
000000a0 25 00 73 00 74 00 72 00 65 00 61 00 6d 00 6e 00 |%.s.t.r.e.a.m.n.|
000000b0 61 00 6d 00 65 00 25 00 5c 00 25 00 73 00 74 00 |a.m.e.%.\.%.s.t.|
000000c0 72 00 65 00 61 00 6d 00 6e 00 61 00 6d 00 65 00 |r.e.a.m.n.a.m.e.|
000000d0 25 00 03 00 00 00 14 00 00 00 5b 00 5d 00 7b 00 |%………[.].{.|
000000e0 7d 00 23 00 24 00 a7 00 25 00 7e 00 5e 00 01 00 |}.#.$…%.~.^…|
000000f0 00 01 00 01 00 01 05 00 00 00 96 00 00 00 03 00 |…………….|
LG/Best regards, Alex

"Journalism is printing what someone else does not want printed. Everything else is public relations."
- George Orwell

D1734FA178BF7D5AE50CB1AD54442494
 
tomhake1
3 Beiträge
schrieb am 19.08.15 um 17:45 Uhrzuletzt bearbeitet von tomhake1 am 19.08.15 um 17:52 Uhr
Link zu diesem Post
Hi alex,

danke für die Infos, da war ich ja auf dem richtigen Weg. Das Entfernen der ertsen 9 Bytes und das Dekomprimieren hatte ich bereits hinbekommen, nur hat es mich gewundert, dass die dekomprimierte Datei bei mir genau so aussieht wie in deinem Beispiel. Ich hatte eine strukturierte Datei erwartet, die man leichter bearbeiten kann. Wie sind die Daten encoded? Egal ob ich die Daten als UTF-8 oder UTF-16 öffne, die NUL characters (bzw. die Leerzeichen zwischen den einzelnen Buchstaben) verschwinden dadurch nicht (außer ich printe den Inhalt der Datei in der Shell), und es gibt immer noch viele Sonderzeichen/Control characters, die ich nicht deuten kann, aber anscheinend die Struktur bestimmen. Hoffe du kannst mir hierzu noch weitere Tipps geben, bevor ich mich weiter im Kreis drehe :)

Danke!

PS: Hast du schon mal über eine alternative Art der Datenspeicherung (z.B. SQLite) nachgedacht? Ich kann mir gerade nicht vorstellen, wie streamWriter ohne viel Aufwand die Datei strukturiert ausliest, mit ner Datenbank ist das aus meiner Erfahrung her einfacher, oder warum hast du diesen Weg gewählt? Das ist übrigens kein Vorwurf, sondern nur Neugier, da ich ein Neuling im Programmieren bin.
 
alex
2440 Beiträge
schrieb am 19.08.15 um 20:23 Uhr
Link zu diesem Post
Nabend.

Das ist eine Binärdatei, nicht ganz einfach für Menschen zu lesen und auch nicht so einfach abfragbar, wie das mit SQL geht. Ich schätze mal, dass das das einfachste und älteste Dateiformat ist. Ausserdem ist es einfach selber zu implementieren. Ich versuche das mal zu erklären:
Die ersten 4 Bytes sind nur dazu da, dass streamWriter weiß, um was es sich bei der Datei handelt, z.B. hat ein exportiertes Profil vorne andere Bytes. Danach kommen 4 Bytes für die Dateiversion, aktuell steht da glaube ich 42 00 00 00, was dezimal 66 wäre, also ist die Dateiversion damit Version 66. Danach kommt ein 01 - das sagt streamWriter, dass die nächsten Bytes komprimiert sind. Würde man da 00 hinschreiben und ab dem zlib-Header die "decompressed.dat" aus meinem Beispiel an die Datei anfügen, würde streamWriter sie z.B. ohne Kompression einlesen. Jetzt wird mit zlib dekomprimiert, danach geht es weiter mit den Nutzdaten. Die nächsten 4 Bytes der entpackten Daten bedeuten, wieviel Bytes von streamWriter schon empfangen wurden. Wenn die Dateiversion größer als 61 ist, bedeuten die nächsten 4 Bytes, wieviel Lieder gespeichert wurden, und so weiter. Damit dieses Einlesen funktioniert, sind an einigen Stellen Abfragen auf die Dateiversion, streamWriter ist bis auf extrem frühe Versionen abwärtskompatibel und könnte jetzt noch eine Datei von vor ein paar Jahren einlesen.
Wegen dem Encoding: Die meisten Daten in der Datei sind ganz einfache Integer oder LongWord, die kannst du so in den meisten Sprachen einlesen. Eventuell muss man was wegen der Endianess einstellen, das kommt dann ganz drauf an. Ein String ist gespeichert als 4 Byte Längenangabe + String, man muss nach Lesen der Längenangabe dann noch "Längenangabe" Bytes lesen, um den String zu bekommen. Das selbe gilt für Listen, erst eine Längenangabe, dann die einzelnen Elemente der Liste. Das Format an sich ist nur in den Quellen von streamWriter dokumentiert. Falls da Bedarf besteht, kann ich dazu etwas mehr (und die Delphi-Quellen natürlich) posten.

Egal ob ich die Daten als UTF-8 oder UTF-16 öffne, die NUL characters (bzw. die Leerzeichen zwischen den einzelnen Buchstaben) verschwinden dadurch nicht (außer ich printe den Inhalt der Datei in der Shell), und es gibt immer noch viele Sonderzeichen/Control characters, die ich nicht deuten kann, aber anscheinend die Struktur bestimmen. Hoffe du kannst mir hierzu noch weitere Tipps geben, bevor ich mich weiter im Kreis drehe :)

Die Textdaten sind als Delphi-Unicode-String gespeichert. Das zweite Byte ist dort pflicht, ich glaube, bei anderen Encodings ist das anders. Etwas bitter, dass ich es jetzt nicht besser weiß, aber etwas Recherche dazu sollte die Antwort bringen. Die restlichen Sonderzeichen kommen eben daher, dass Zahlen nicht als Text, sondern in Binärform gespeichert werden. Je nach Zahl können da also lustige "Zeichen" (die ja nicht als Zeichen zu interpretieren sind) in der Textansicht der Datei stehen.

PS: Hast du schon mal über eine alternative Art der Datenspeicherung (z.B. SQLite) nachgedacht? Ich kann mir gerade nicht vorstellen, wie streamWriter ohne viel Aufwand die Datei strukturiert ausliest, mit ner Datenbank ist das aus meiner Erfahrung her einfacher, oder warum hast du diesen Weg gewählt? Das ist übrigens kein Vorwurf, sondern nur Neugier, da ich ein Neuling im Programmieren bin.

Der "ohne Viel Aufwand"-Punkt ist ja schon oben etwas erklärt, das ganze ist nämlich nicht besonders kompliziert. Es sieht nur als Text "komisch" aus. Die Datenbank würde hier besonders schön sein, weil ja nicht mehr alle Daten auf einmal im Speicher stehen würden. Die Datenmengen sind aber noch nicht groß genug, um so einen krassen (mittlerweile fast unmöglichen) Umbau rechtzufertigen. Dadurch, dass der komplette Inhalt der Datei nach dem Laden im Speicher in Objekten gehalten wird, kann ich mit den Daten ganz einfach und bequem arbeiten.

Ich hoffe, das hilft erstmal etwas beim Verständnis…
LG/Best regards, Alex

"Journalism is printing what someone else does not want printed. Everything else is public relations."
- George Orwell

D1734FA178BF7D5AE50CB1AD54442494
 
tomhake1
3 Beiträge
schrieb am 21.08.15 um 16:42 Uhr
Link zu diesem Post
Hallo alex,

noch einmal vielen Dank für Deine ausführliche Antwort. Jetzt habe ich auf jeden Fall mehr über den Aufbau und das Parsen der Datei verstanden (aber bestimmt immer noch nicht alles). Diese obligatorischen 2-Bytes für Unicode kenne ich teilweise aus Java, Delphi hat hier bestimmt auch seine Eigenheiten und mit Hilfe von Google bekomme ich die Datei vermutlich sauber dekodiert. Ich werde die nächsten Tage etwas rumexperimentieren und melde mich dann mit den Ergebnissen (oder weiteren Fragen :P).

Übrigens praktische Idee mit der Versionierung und Rückwärtskompatibilität, so kann mans auch machen, wieder was gelernt! Mit dem Aufwand für eine Umstellung auf eine Datenbank als Settings-Speicher gebe ich dir Recht, aber sieh es mal so: Kein anderes Programm kommt an die Funktionalität von streamWriter heran und ich könnte wetten, dass wenn du deinen Code als Open Source veröffentlichst, vieeele User beitragen würden, um das und noch viele andere großartige Features zu ermöglichen. Ich habe mal geschaut, du scheinst mal ein Repo angelegt zu haben (https://www.openhub.net/p/streamwriter), das ist aber momentan nicht mehr gepflegt, oder?

 
alex
2440 Beiträge
schrieb am 22.08.15 um 01:34 Uhrzuletzt bearbeitet von alex am 22.08.15 um 01:36 Uhr
Link zu diesem Post
Moin!

Ich werde die nächsten Tage etwas rumexperimentieren und melde mich dann mit den Ergebnissen (oder weiteren Fragen :P).

Mit etwas Probiererei kommst du auf jeden Fall an alle Daten dran. Man muss eben nur die Struktur herausfinden - die ist aber wie gesagt auch in den streamWriter-Quellen "codemäßig" dokumentiert, das Angebot die Sachen hier zu posten steht weiterhin. Da müsstest du dich dann dran lang hangeln.
Was mir noch eingefallen ist, aber was ich vergessen habe, das letzte mal zu posten: Wenn du einfach nur eine URL ändern möchtest geht das auch einfacher, du kannst es mal mit einem Hex-Editor testen. Ich bin mir sicher, dass es funktioniert, ist aber ungetestet. Du suchst erst mal in den dekomprimierten Daten nach der URL, das ist ja kein Problem. Dann schaust du auf die 4 Bytes vor dem ersten Buchstaben der URL - das ist die Längenangabe. Wenn du die URL änderst, musst du nur diese Längenangabe anpassen, und dann sollte alles funktionieren. Wenn die neue URL kürzer ist als die in der Datei gespeicherte sollte es auch reichen, den Rest des Strings mit 00 aufzufüllen, die Längenangabe kann dann ruhig größer sein als der String, Delphi interpretiert glaube ich 00 00 als String-Ende, so dass es keine Probleme beim Lesen geben sollte.

Übrigens praktische Idee mit der Versionierung und Rückwärtskompatibilität, so kann mans auch machen, wieder was gelernt! Mit dem Aufwand für eine Umstellung auf eine Datenbank als Settings-Speicher gebe ich dir Recht, aber sieh es mal so: Kein anderes Programm kommt an die Funktionalität von streamWriter heran und ich könnte wetten, dass wenn du deinen Code als Open Source veröffentlichst, vieeele User beitragen würden, um das und noch viele andere großartige Features zu ermöglichen. Ich habe mal geschaut, du scheinst mal ein Repo angelegt zu haben (https://www.openhub.net/p/streamwriter), das ist aber momentan nicht mehr gepflegt, oder?

Jede Ansicht in streamWriter ist zur Zeit darauf ausgelegt, dass alle Daten immer im Speicher verfügbar sind. Bei einer Umstellung müssten alle Anzeige-Routinen (das sind viele) und alle Daten-ändern-Routinen angepasst werden. Dann kommt noch dazu, dass ein Update der Daten in der DB auch ein neues Laden der Daten, die angezeigt werden, auslösen müsste, und so weiter - das geht eben zur Zeit recht einfach, weil meine "Datenbank" immer im Speicher ist und alle Elemente in der grafischen Darstellung direkt mit diesen Daten, die immer da sind, arbeiten. Es ist fast unmöglich, das jetzt zu ändern, außer man baut viele Sachen von Grund auf neu - die Zeit fehlt mir leider, streamWriter ist ja jetzt schon eigentlich ein Projekt, wo ich nur schaue, dass es lebt (Server am Laufen halten, etc) - viel passiert da erst mal nicht.
streamWriter ist Open-Source (GPL), deshalb gab es auch mal ein Repo. Weil aber nach langer Zeit niemand in die Entwicklung einsteigen wollte, und die Leute, die "einsteigen" wollten streamWriter und meine Hilfe beim Kompilieren nur dazu genutzt haben, eine Abzock-Software aus streamWriter zu bauen, habe ich das etwas zurückgefahren (z.B. keine Downloadlinks zum Source mehr auf dieser Webseite). Ausserdem ist es leider so, dass man den kompletten streamWriter nur kompilieren kann, wenn man eine Delphi-Lizenz besitzt, die Geld kostet. Dazu ist streamWriter dann noch ein Windows-only Programm. Das macht es leider nicht besonders attraktiv für Menschen, die bei der Entwicklung helfen könnten. Wäre ich vor vielen Jahren schlauer gewesen und hätte das alles so gebaut, dass man eine QT- und Web-Oberfläche zum bedienen von sW hat, würde das jetzt vielleicht etwas anders aussehen.
Das ändert aber nichts an der Lizenz - Wenn du die Sourcen haben möchtest sag Bescheid. Ich kann dann noch ein paar Worte mit auf den Weg geben, wo Daten geladen werden, und dann müsstest du dich da durch kämpfen;-)
LG/Best regards, Alex

"Journalism is printing what someone else does not want printed. Everything else is public relations."
- George Orwell

D1734FA178BF7D5AE50CB1AD54442494