AutoIt ist so eine feine Sprache. Gibt es wirklich keine Möglichkeit, direkt auf ein Zeichen in einem String zuzugreifen?
So wie bei C++ : string[x].
Muss man immer über zeitaufwendige Funktionen (StringMid usw.) gehen?
AutoIt ist so eine feine Sprache. Gibt es wirklich keine Möglichkeit, direkt auf ein Zeichen in einem String zuzugreifen?
So wie bei C++ : string[x].
Muss man immer über zeitaufwendige Funktionen (StringMid usw.) gehen?
in wiefern zeitaufwändig?
kannst dir ja eine eigene funktion bauen, in etwa:
string($str,$cnt)
string("test",2) = e
is doch kein problem
Wenn ich z.B. eine Bitmap-Datei, die aus 20 MByte besteht, bearbeiten möchte und dort Millionen von Zeichen austausche will, dann dauert das ewig.
Du kannst besagte Bitmap-Datei in einer Struct (char/wchar/etc[x]) speichern und mittels DllStructGet-/SetData auf die einzelnen Elemente zugreifen.
; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +
[/autoit][autoit][/autoit][autoit]Global $cStr = StrToCStr('Make-Grafik')
Global $i
For $i = 1 To CStrLen($cStr)
MsgBox(262144, 'Example', CStrChar($cStr, $i))
Next
; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +
[/autoit][autoit][/autoit][autoit]Func StrToCStr($sString)
Local $iLen = StringLen($sString)
Local $tStruct = DllStructCreate('char[' & $iLen & ']; int')
DllStructSetData($tStruct, 1, $sString)
DllStructSetData($tStruct, 2, $iLen)
Return $tStruct
EndFunc
Func CStrChar(ByRef $tStruct, $iIndex)
Return DllStructGetData($tStruct, 1, $iIndex)
EndFunc
Func CStrLen(ByRef $tStruct)
Return DllStructGetData($tStruct, 2)
EndFunc
; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +
[/autoit]Erst einmal recht herzlichen Dank!
Das muss ich mir noch in Ruhe auf der Zunge zergehen lassen.
Melde mich dann wieder.
Nochmals Euch vielen Dank!
Wenns allein um die Syntax geht kannst du einen String in AutoIt auch in ein zeichenweises Array konvertieren.
Hier mal ein Beispiel:
[autoit]#include "Array.au3"
[/autoit][autoit][/autoit][autoit]Global Const $s_String = "Hallo Welt"
[/autoit][autoit][/autoit][autoit]Global $a_ASCII = StringToASCIIArray($s_String)
_ArrayDisplay($a_ASCII, "ASCII-Array")
Global $a_Chars = StringSplit($s_String, "", 2)
_ArrayDisplay($a_Chars, "Char-Array")
Wenn ich z.B. eine Bitmap-Datei, die aus 20 MByte besteht, bearbeiten möchte und dort Millionen von Zeichen austausche will, dann dauert das ewig.
Bitmaps solltest du nicht als Zeichenkette verarbeiten.
Nutz stattdessen die DllStructs.
Aber auch da ist zu sagen: Dafür ist AutoIt schlicht nicht gemacht - wirklich performant wirst du es mit AutoIt alleine nicht hinbekommen.
ZitatWenn ich z.B. eine Bitmap-Datei, die aus 20 MByte besteht, bearbeiten möchte und dort Millionen von Zeichen austausche will, dann dauert das ewig.
Sagt wer?
Na dann zeig mal dein Script, was so "ewig" dauert...
Guckst du:
$a = ""
for $i = 32 to 132 ;100 Byte "Paket" erstellen, "Fixed Length Block"
$a &= Chr($i)
next
for $i = 1 to 18 ;bissl spielen von 10-20
$a &= $a
next
ConsoleWrite(Int(StringLen($a) / 1e6) & "MB" & @crlf)
[/autoit] [autoit][/autoit] [autoit]$t=timerinit()
$b=stringreplace($a,"ABC","XXX",0,1)
$anz=@extended
consolewrite("Innerhalb von " & stringformat("%.3f",timerdiff($t)/1000) & "Sekunden wurden in "&stringlen($a)& " Bytes genau " & $anz &" Ersetzungen durchgeführt." & @crlf)
tauscht auf meinem langsamen Gurkenrechner in 180ms innerhalb von 26MB genau 262144x ABC in XXX, also genau das, was ein "Pixelumschreiber" für RGB-Daten auch machen würde.
Also 1,3MB Daten tauschen pro Sekunde...dauert ewig?!
In Kombination Eurer umfangreichen Anregungen habe ich folgendes Programm geschrieben:
[autoit]
#include "HilfsFunktionen.au3"
Global $Protokoll1=2 ; =2, dann wird protokolliert
; =0, dann wird nicht protokolliert
$ProgrammName="Test1" ; für Protokoll
;-------------------------------------------------------------------------
Protokoll("Anfang")
$datei="d:\arbdat\Alarmanlage 2a.bmp"
$handl=FileOpen ($datei)
$feld=FileRead ( $handl)
$anz=@extended
FileClose ( $handl)
Local $a = StringToASCIIArray($feld)
Protokoll("Anzahl:"&$anz)
For $i=0 To $anz-2
$a[$i]=$a[$i+1]
Next
Protokoll("AAAA")
Local $s = StringFromASCIIArray($a)
Protokoll("BBBB")
$handl=FileOpen("d:\arbdat\Alarm.bmp",2)
FileWrite ($handl,$s)
FileClose ( $handl)
Protokoll("Ende")
Das Protokoll sieht dann so aus:
Programmname: Test1
2013/11/27 09/53/39
..........Zeit(sec)
Test1 0.000306 Anfang
Test1 2.149016 Anzahl:6714366
Test1 7.097853 AAAA
Test1 7.886551 BBBB
Test1 7.900876 Ende
Das alles als nur in 8 Sekunden. Ihr könnt Euch vorstellen, dass ich jetzt höchst zufrieden bin.
Ich danke Euch allen für Eure Mühe mit mir.
Wenn du nur einmal eine Datei ausliest und nur einmal schreibst reicht ein FileRead/Write mit Dateiname statt Handle aus.
Im Hintergrund wird dann sowieso implizit FileOpen und FileClose ausgeführt.
Sehe ich das aber richtig, dass du einfach nur alle Bytes jeweils um eine Position nach vorne verschieben willst?
Wenn ja - dann solte folgendes einfacher und schneller gehen:
#include <Constants.au3>
[/autoit][autoit][/autoit][autoit]; Alte Datei ohne erstes Byte einlesen:
$h_File = FileOpen("Test.bmp", 16)
FileSetPos($h_File, 1, $FILE_BEGIN)
$b_File = FileRead($h_File)
FileClose($h_File)
; Neue Datei schreiben:
FileWrite("Test_out.bmp", $b_File)
Nein, das sollte nur zeigen, wie schnell es gehen würde, selbst wenn man alle 6,7 MByte Zeichen einzeln austauscht.
Dein Hinweis auf die Funktion StringToASCIIArray war sehr wichtig, dadurch bin ich dann auch auf die erst recht wichtige Funktion StringFromASCIIArray aufmerksam geworden.
Gruß
Dieter
Hi,
was hat denn ein StringToASCIIArray in einem Script zur Bearbeitung von Bitmaps zu suchen?
Die Bitmap-Daten liegen bereits in einem Array, nämlich nacheinander im Speicher, zu adressieren über ihre Adresse oder x- und y-Koordinaten!
Du liest also ein Array in ein anderes Array ein, läufst dann durch den Code um schlussendlich das Array wieder in ein Array zu schreiben?! Und eröffnest Threads mit dem Hinweis auf C++ und dessen "Geschwindigkeit?!
ZitatSo wie bei C++ : string[x].
Mit Verlaub, programmiertechnisch hochgradigiger Dünnsch****.
Mittlerweile ist mir klar, wieso Software immer langsamer wird, wenn man mit der Aussage konfrontiert wird "muss schnell sein, ist doch in C++ geschrieben!"
Wie schon von AspirinJunkie in Post 7 vorgeschlagen, lies die Bitmap in eine Struct ein, bearbeite dort deine "Pixel" bzw. Bereiche je nach Gusto, und wenn DANN Geschwindigkeit fehlt, schreibt man ggf eine Funktion in einigen Zeilen C als Dll, und ruft diese von AutoIt mit der Startadresse der Struct als Parameter auf.
Beispiele für Bitmap-Be- und Verarbeitung gibt es reichlich hier im Forum, fast die Hälfte aller ASM-Scripte befassen sich mit Bitmaps, u.a. deswegen, weil deren Struktur so einfach ist.