unix > windows Dateiconverter

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Lebostein
Beiträge: 674
Registriert: 13.09.2004 11:31
Wohnort: Erzgebirge

unix > windows Dateiconverter

Beitrag von Lebostein »

Hi,

ich möchte einige Dateien von einem Unix-System übernehmen. In der Datei sind hintereinanderweg nur LONG-Variablen (4 Byte) gespeichert. Damit ich sie unter Windows auslesen kann, muss ich nun jede LONG-Variable 'umdrehen', d.h. was vorher das 1.Byte der Variable war, muss jetzt dass 4.Byte sein usw. Mein Vorgehen: Datei in Speicher einlesen, Longs umdrehen, datei wieder speichern:

Code: Alles auswählen

quelle$ = "d3plot"
ziel$ = quelle$ + "_conv"

;---------------------------------
;Quelldatei in den Speicher lesen
;---------------------------------
ReadFile(0, quelle$)
data_length = Lof()
data_adress = AllocateMemory(data_length)
ReadData(data_adress, data_length)
CloseFile(0)

;---------------------------------
;Speicher modifizieren
;---------------------------------
longs = data_length >> 2
zeiger = data_adress

For count = 1 To longs
b1 = PeekB(zeiger + 0)
b2 = PeekB(zeiger + 1)
b3 = PeekB(zeiger + 2)
b4 = PeekB(zeiger + 3)
PokeB(zeiger + 0, b4)
PokeB(zeiger + 1, b3)
PokeB(zeiger + 2, b2)
PokeB(zeiger + 3, b1)
zeiger + 4
Next count

;---------------------------------
;Speicher in Zieldatei schreiben
;---------------------------------
CreateFile(0, ziel$)
WriteData(data_adress, data_length)
CloseFile(0)

;---------------------------------
;Ende der Konvertierung
;---------------------------------
MessageRequester("Meldung", "Fertig!")
Kann man diesen Code beschleunigen? Irgendwie muss das umdrehen der Bytes doch einfacher gehen, oder? Vielleicht hat ja auch jemand ne ASM-Lösung parat. Danke schonmal.
FloHimself
Beiträge: 338
Registriert: 05.09.2004 18:47

Beitrag von FloHimself »

Code: Alles auswählen

Structure byteorder
  byte1.b
  byte2.b
  byte3.b
  byte4.b
EndStructure

foo.byteorder
foo\byte1 = 1
foo\byte2 = 2
foo\byte3 = 3
foo\byte4 = 4

Debug foo\byte1
!MOV Eax, [v_foo]
!BSWAP Eax
!MOV [v_foo], Eax
Debug foo\byte1

foo2 = 14
!MOV Eax, [v_foo2]
!BSWAP Eax
!MOV [v_foo2], Eax
Debug foo2
Benutzeravatar
Lebostein
Beiträge: 674
Registriert: 13.09.2004 11:31
Wohnort: Erzgebirge

Beitrag von Lebostein »

Ah, super! Danke! Genau sowas hab ich gesucht.

Wie kann ich denn statt einer Variablen 'v_variable' eine Speicheradresse angeben?
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Beitrag von GPI »

Liegt übrigends nicht am OS, sonder an der CPU. Die Intel-Variante find ich persönlich unglücklich...
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
Zaphod
Beiträge: 2875
Registriert: 29.08.2004 00:40

Beitrag von Zaphod »

eine variable ist eine speicheradresse... mit zeigern müßte das genauso funktionieren. oder verstehe ich dich jetz falsch?
FloHimself
Beiträge: 338
Registriert: 05.09.2004 18:47

Beitrag von FloHimself »

Warum nicht so?

Code: Alles auswählen

#SOURCE_FILE$ = "C:\source.dmp"
#TARGET_FILE$ = "C:\target.dmp"

If ReadFile(0, #SOURCE_FILE$)
  If CreateFile(1, #TARGET_FILE$) 
    While Eof(0) = 0
      UseFile(0)
      var.l = ReadLong()
      !MOV Eax, [v_var] 
      !BSWAP Eax 
      !MOV [v_var], Eax
      UseFile(1)
      WriteLong(var)
    Wend
    CloseFile(1)
  EndIf
  CloseFile(0)
EndIf
Benutzeravatar
Lebostein
Beiträge: 674
Registriert: 13.09.2004 11:31
Wohnort: Erzgebirge

Beitrag von Lebostein »

FloHimself hat geschrieben:Warum nicht so?

Code: Alles auswählen

#SOURCE_FILE$ = "C:\source.dmp"
#TARGET_FILE$ = "C:\target.dmp"

If ReadFile(0, #SOURCE_FILE$)
  If CreateFile(1, #TARGET_FILE$) 
    While Eof(0) = 0
      UseFile(0)
      var.l = ReadLong()
      !MOV Eax, [v_var] 
      !BSWAP Eax 
      !MOV [v_var], Eax
      UseFile(1)
      WriteLong(var)
    Wend
    CloseFile(1)
  EndIf
  CloseFile(0)
EndIf
Weil das Auslesen jeder einzelnen Long-Variable aus einer Datei wesentlich langsamer ist, als die komplette Datei mit einem Ruck in den Speicher zu laden. Wenn ich zum Beispiel eine 70MB-Datei auf die Routinen anwende, erhalte ich folgendes Ergebnis:

Lebosteins Variante (Datei komplett in den Speicher): 4 Sekunden
FloHimselfs Variante (Jede Variable einzeln auslesen): 195 Sekunden

also fast 50 mal schneller.
Zaphod hat geschrieben:eine variable ist eine speicheradresse... mit zeigern müßte das genauso funktionieren. oder verstehe ich dich jetz falsch?
Wenn ich den Assembler-Code richtig deute, dann wird mit !MOV Eax, [v_var] der Inhalt der Variable an das Register Eax übergeben. Was muss ich aber schreiben, wenn ich nicht den Inhalt der Variable übergeben will, sondern den Inhalt der Speicheradresse, auf die meine Zeiger-Variable zeigt?
FloHimself
Beiträge: 338
Registriert: 05.09.2004 18:47

Beitrag von FloHimself »

Lebostein hat geschrieben:Wenn ich zum Beispiel eine 70MB-Datei auf die Routinen anwende...
Konnte ja nicht wissen, das du solche Daten schaufelst ;)

Tausch mal in deinem Programm die schleife gegen diese:

Code: Alles auswählen

For count = 1 To longs 
!MOV Eax, [v_zeiger]
!MOV Ebx, Eax
!MOV Eax, [Eax]
!BSWAP Eax
!MOV [Ebx], Eax
!ADD [v_zeiger], 4
Next count 
Benutzeravatar
Deeem2031
Beiträge: 1232
Registriert: 29.08.2004 00:16
Wohnort: Vorm Computer
Kontaktdaten:

Beitrag von Deeem2031 »

FloHimself hat geschrieben:

Code: Alles auswählen

For count = 1 To longs 
!MOV Eax, [v_zeiger]
!MOV Ebx, Eax
!MOV Eax, [Eax]
!BSWAP Eax
!MOV [Ebx], Eax
!ADD [v_zeiger], 4
Next count 
So müsste das noch einen Tick schneller gehen:

Code: Alles auswählen

!MOV Edx, dword [v_longs]
!MOV Ebx, dword [v_zeiger]
!iasm_loop1_s:
!OR Edx, Edx
!JZ iasm_loop1_e
!MOV Eax, dword [Ebx]
!BSWAP Eax
!MOV dword [Ebx], Eax
!DEC Edx
!ADD Ebx, 4
!JMP iasm_loop1_s
!iasm_loop1_e:
Bild
[url=irc://irc.freenode.org/##purebasic.de]irc://irc.freenode.org/##purebasic.de[/url]
Benutzeravatar
Lebostein
Beiträge: 674
Registriert: 13.09.2004 11:31
Wohnort: Erzgebirge

Beitrag von Lebostein »

FloHimself hat geschrieben:Konnte ja nicht wissen, das du solche Daten schaufelst ;)
Jup, so um die 70 MB pro Datei, und das für etwa 1500 Dateien (ernsthaft, kein Scherz!)

@Flo, @Deeem2031, vielen Dank für eure Lösungen. Ich kann jede Millisekunde Einsparung gut gebrauchen.

Noch ne Frage: Nützt mir an dieser Stelle die vielgelobte FastFile-Libary was?



PS: Hab ich gestern mal ein wenig mit ASM beschäftigt. Diese Variante ist doch auch ok, oder?:

Code: Alles auswählen

!MOV Ebx, [v_zeiger]

For count = 1 To longs

!MOV Eax, [Ebx]
!BSWAP Eax
!MOV [Ebx], Eax
!ADD Ebx, 4

Next count
Antworten