 |
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
jb

Anmeldungsdatum: 14.01.2005 Beiträge: 2010
|
Verfasst am: 22.03.2005, 20:50 Titel: Dateimodus 'BINARY' |
|
|
Hallo!
Ich bitte im Voraus für etwas Geduld, da ich nicht der beste Erklärer bin.
Ich habe versucht, eine .EXE und eine .TXT-Datei in eine .PAK Datei zu packen.
Das soll so eine Art Komprimierung darstellen. Diese Datei wird im Binärmodus erstellt.
Nun muss der "Entpacker" ja auch wissen, wo er was abspeichern soll.
Deshalb steht in der .PAK-Datei der Dateiname am Anfang, umgeben (je rechts und links)
von dem Zeichen mit dem ASCII-Code 178.
Das Prog liest nun Byte für Byte ein, und überprüft jedesmal, ob sich eingelesene Byte
der ASCII-Code 178 ist.
Wenn dies so ist, addiert er alle nachfolgenden Zeichen (bis wiederum ein
ASCII-Code 178 folgt) dem Dateinamen Pfad$ hinzu.
Nun schreibt er alle nachfolgenden Zeichen in die entsprechende Datei.
Wenn nun ein "@" folgt, beendet der Entpacker.
Wenn ich aber den Dateinamen mit PRINT anzeige, sehe ich keinen Fehler
im selbigen.
Aber wenn nun die Datei geöffnet werden soll, steht da: 'Ungültiger
Dateiname', und nichts geht mehr.
Bsp: Vorher war Pfad$ = "A:\ABC.TXT"
und nachher eine hübsche Ansammlung wildfremder Zeichen (z.B. die ASCII-Codes von 1-31).
Wo liegt das Problem??
Hier der Code:
Code: |
DIM byte AS STRING * 1
OPEN "A:\KOMP.PAK" FOR BINARY AS #1
Pfad$ = "A:\"
REM Der Pfadname wird "rausgefiltert"
DO
GET #1, , byte
IF ASC(byte) <> 178 THEN Pfad$ = Pfad$ + byte ELSE EXIT DO
LOOP
REM Hier geht noch alles
PRINT CHR$(34) + Pfad$ + CHR$(34) + " wird erstellt..."
REM Aber HIER kommt der Fehler
--> OPEN Pfad$ FOR BINARY AS #3 <--
DO
GET #1, , byte
IF byte = "@" THEN EXIT DO
PUT #3, , byte
LOOP
CLOSE #3
|
jb |
|
Nach oben |
|
 |
Stephan

Anmeldungsdatum: 05.10.2004 Beiträge: 358 Wohnort: Hessen - 20km Nördlich von Frankfurt am Main
|
Verfasst am: 22.03.2005, 23:20 Titel: |
|
|
Öffne mal deine PAK datei mit einem Hex editor, und kontrolliere ob alles richtig geschrieben wurde.
Ich würde aber an deiner stelle den ganzen aufbau etwas Ändern.
Was passiert z.b. wenn du eine EXE datei hinzufügst, in der das Zeichen "@" im Hexcode vorkommt,
dann funktioniert dein programm schon nichtmehr.
Vielleicht ein kleiner ansatz, wie du soetwas einfacher hinbekommen kannst.
Erstmal einen Block für die Dateinamen & Größen Reservieren (im prinzip eine art TOC)
z.b.
50 Bytes Dateiname , 4 Byte Datei Anfang in der PAK Datei , 4 Byte Datei Größe
Du schreibst einfach den Dateinamen in Tabelle,und lässt die Reslichen Bytes (der 50 Bytes) leer (CHR$(0))
somit kannst du den Namen schonmal gut auslesen.
Und durch die Tabelarische Anordnung ist es auch kein problem mal schnell
eine Dateigröße auszulesen,um eine Datei weiter unten zu Extrahieren.
Dadurch kannst du dir z.b. ganz einfach eine Formel erstellen,mit der du zu jeden punkt in der Liste springen kannst. _________________ 'Wir schätzen die Zeit erst, wenn uns nicht mehr viel davon geblieben ist.'
Leo Tolstoi |
|
Nach oben |
|
 |
jb

Anmeldungsdatum: 14.01.2005 Beiträge: 2010
|
Verfasst am: 23.03.2005, 10:35 Titel: |
|
|
Die Datei ist korrekt aufgebaut, und in der .EXE und in der.TXT Datei sind
keine @-Zeichen enthalten.
Aber vielen Dank für den Tipp!
jb |
|
Nach oben |
|
 |
Stephan

Anmeldungsdatum: 05.10.2004 Beiträge: 358 Wohnort: Hessen - 20km Nördlich von Frankfurt am Main
|
Verfasst am: 23.03.2005, 10:59 Titel: |
|
|
Nochmal zu den EXE Dateien,
Ich hab mal schnell nachgeschaut, und habe bei mir KEINE Win32 EXE Gefunden,
an der nicht an Position 24 ein "@" vorkahm.
Bei Dos EXE Dateien hatte ich im Header sogar noch viel mehr.
d.h. selbst wenn das Namen auslesen bei dir funktioniert,wirst du spätestens beim auslesen der EXE
riesen probleme bekommen.
Teste es selbst, Benutze mal die Windows Such Funktion,
gib als Namen *.EXE ein , und als Enthaltenen text ein "@" ein,
du wirst sehen.
(Ich hab auf C:\ 920 EXE dateien, davon enthalten 917 ein @) _________________ 'Wir schätzen die Zeit erst, wenn uns nicht mehr viel davon geblieben ist.'
Leo Tolstoi |
|
Nach oben |
|
 |
jb

Anmeldungsdatum: 14.01.2005 Beiträge: 2010
|
Verfasst am: 23.03.2005, 13:30 Titel: |
|
|
Okay, deine Methode ist wohl die bessere...
Ich habe das jetzt so gemacht:
1. Teil: Dateiname (Byte 1-100)
2. Teil: Dateigröße in Bytes (Bytes 101-500)
3. Teil: Daten (Bytes 500 bis ???)
4. Weiter
Alle Leerstellen habe ich mit CHR$(0) ausgefüllt.
Das Auslesen funktioniet so:
1. Öffne die "gepackte" Datei
2. Hole 100 mal je ein Byte, wenn es sich nicht um CHR$(0) handelt, hänge es dem Pfadnamen an.
3. Hole die Größe.
Hier steckt ein Problem. byte ist eine Variable vom TYpe STRING * 1, da ich vorher immer
einen Überlauf-Fehler bekam.
Nun wird hier genauso wie bem Dateinamen verfahren: Hole 500mal ein
Byte, wenn es sich nicht um CHR$(0) handelt, füge es dem Dateigrößen-String an.
Nun muss ich irgendwann den String in eine brauchbare Zahl umwandeln.
Doch genau hier steckt das Problem, da komme ich nicht weiter.
Da steht dann zum Beispiel: Ñ7☺.
Wie zum Teufel daraus eine Dateilänge ermitteln?
Weiß jemand Rat?
jb |
|
Nach oben |
|
 |
Mecki Igel

Anmeldungsdatum: 10.09.2004 Beiträge: 985 Wohnort: Niederbayern
|
|
Nach oben |
|
 |
Skilltronic

Anmeldungsdatum: 10.09.2004 Beiträge: 1148 Wohnort: Köln
|
Verfasst am: 23.03.2005, 14:51 Titel: |
|
|
Hallo!
Wie wandelst du denn die Dateilänge beim Schreiben in ASCII-Zeichen um?
Wenn du Dateien hast, die grösser als 256 Byte sind, musst du die Grösse auf mehrere Byte verteilen. So wie eine Integer-Variable auch aus zwei Byte besteht um Zahlen von -32768 bis 32767 aufnehmen zu können. Beim Lesen diese Bytes dann wieder zusammensetzen. Vier, maximal 16 Byte sollten dafür auch genügen. 400 Sind etwas übertieben. Ich glaube, dass würde für Dateien ausreichen, die das gesamte Wissen der Menschheit enthalten.
Gruss
Skilltronic _________________ Elektronik und QB? www.skilltronics.de ! |
|
Nach oben |
|
 |
jb

Anmeldungsdatum: 14.01.2005 Beiträge: 2010
|
Verfasst am: 23.03.2005, 22:37 Titel: |
|
|
Hab's jetzt anders gelöst:
Die Dateigröße wird errechnet, dann im String Groesse$ abgespeichert,
dann wird der String abgescannt, und der ASCII-Code von MID$(Groesse$, i, 1) gespeichert.
Beim Lesen wird der String dann genauso zusammengesetzt und anschließend
wieder in eine Zahl umgewandelt.
Ist zwar etwas kompliziert, aber es klappt...
jb |
|
Nach oben |
|
 |
Skilltronic

Anmeldungsdatum: 10.09.2004 Beiträge: 1148 Wohnort: Köln
|
Verfasst am: 25.03.2005, 13:32 Titel: |
|
|
Hallo!
Ich habe dir hier mal ein kleines Beispiel geschrieben, das die Länge einer Datei in 8 Byte zerlegt, daraus einen String erstellt und aus diesem wieder die Zahl. Man muss sich nur klarmachen, dass es dabei um den Stellenwert der einzelnen Bytes geht, ganau wie bei den Bits innerhalb des Bytes.
Code: | CLS
'Dateilaenge ermitteln
OPEN "datei.dat" FOR BINARY AS #1
dl# = LOF(1)
CLOSE 1
PRINT "Dateilaenge:"; dl#; "Byte"
'Diese Zahl in einen 8-stelligen String umwandeln
text$ = ""
FOR a = 7 TO 0 STEP -1
p# = 256 ^ a
byte = FIX(dl# / p#)
text$ = text$ + CHR$(byte)
dl# = dl# - byte * p#
NEXT
PRINT "String:"; text$
PRINT "Dateilaenge:"; dl#; "Byte"
'Und aus dem String wieder eine Zahl machen
FOR a = 7 TO 0 STEP -1
p# = 256 ^ a
byte = ASC(MID$(text$, 8 - a, 1))
dl# = dl# + byte * p#
NEXT
PRINT "Dateilaenge:"; dl#; "Byte" |
Wenn eines der Zeichen zufälig einen Zeilenvorschub oder so enthält, kann es im Beispiel etwas seltsam aussehen, normalerweise lässt man sich den String aber ja nicht anzeigen.
Gruss
Skilltronic _________________ Elektronik und QB? www.skilltronics.de ! |
|
Nach oben |
|
 |
jb

Anmeldungsdatum: 14.01.2005 Beiträge: 2010
|
Verfasst am: 26.03.2005, 15:52 Titel: |
|
|
THX, Skilltronic!
Ich hab's inzwischen anders gelöst:
Code: |
REM Speichern einer Zahl:
Zahl = 1785
z$ = RTRIM$(LTRIM$(STR$(Zahl$)))
DIM byte AS STRING * 1
FOR i = 1 TO LEN(z$)
byte = MID$(z$, i, 1)
PUT #1, , byte
NEXT i
REM *****************************
REM Laden einer Zahl:
DIM byte AS STRING * 1
DO
GET #1, , byte
IF byte > CHR$(9) THEN EXIT DO
z$ = z$ + byte
LOOP
FOR i = 1 TO LEN(z$)
Zahl$ = Zahl$ + STR$(ASC(MID$(z$, i, 1)))
NEXT i
GeladeneZahl = VAL(Zahl$)
|
Dabei wird beim Speichern immer ein Zeichen mit MID$ isoliert, dann
wird dieses als Byte geschrieben. Beim Lesen wird dann einem String solange
der ASCII-Wert des eben gelesenen Bytes zugeordnet, bis dieses größer
als 9 ist.
Nun muss man den String nur noch in eine Zahl umwandeln.
jb |
|
Nach oben |
|
 |
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|