Seite 1 von 1

unix > windows Dateiconverter

Verfasst: 17.01.2005 11:32
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.

Verfasst: 17.01.2005 15:45
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

Verfasst: 17.01.2005 17:04
von Lebostein
Ah, super! Danke! Genau sowas hab ich gesucht.

Wie kann ich denn statt einer Variablen 'v_variable' eine Speicheradresse angeben?

Verfasst: 17.01.2005 21:14
von GPI
Liegt übrigends nicht am OS, sonder an der CPU. Die Intel-Variante find ich persönlich unglücklich...

Verfasst: 17.01.2005 21:25
von Zaphod
eine variable ist eine speicheradresse... mit zeigern müßte das genauso funktionieren. oder verstehe ich dich jetz falsch?

Verfasst: 18.01.2005 01:14
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

Verfasst: 18.01.2005 09:02
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?

Verfasst: 18.01.2005 23:04
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 

Verfasst: 19.01.2005 00:07
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:

Verfasst: 19.01.2005 08:48
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