Verwirrung. Unicode/Asci, wann wo was

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
GlassJoe
Beiträge: 108
Registriert: 11.06.2017 20:25
Computerausstattung: 2 x AMD Phenom II x4 945,2x Dell Latitude X300, Dell Latitude D410, Hp Compaq NC4400

Re: Verwirrung. Unicode/Asci, wann wo was

Beitrag von GlassJoe »

NicTheQuick hat geschrieben:Ich möchte nicht erneut alle Frage beantworten, aber noch etwas zu Codepages sagen. Die stammen eigentlich aus der Zeit, zu der jedes Zeichen nur 8 Bit hatte, also vergleichbar zu ASCII.
In 8 Bit kann man nur 256 verschiedene Zeichen stecken. Ein Teil davon sind Steuerzeichen, ein Teil repräsentiert das lateinische Alphabet, ein Teil Umlaute, Zeichen mit Akzenten, usw. Aber das ist nur in der Codepage so, die wir hier bei uns kennen. Es gibt noch Codepages, bei denen an Stelle unserer Buchstaben ganz andere stehen, dazu gehören Kyrillisch, griechisch, Thai, Japanisch und viele mehr. Im Grunde wird jeder Wert zwischen 0 und 255 auf ein Zeichen gemappt, das auch wieder eine bestimmte Nummer hat, die man in der Schriftartendatei finden kann. Da man auf diese Weise niemals alle Zeichen der Sprachen auf der Welt unter einen Hut kriegen konnte ohne Codepages zu wechseln, gibt es eben UTF-8, Unicode und Konsorten.

Das Problem an UTF-8 ist, dass jedes Zeichen entweder 8, 16, 24 oder 32 Bit haben kann, man also aus der Bytelänge, die ein UTF-8-String im Speicher belegt, nicht sicher die Zeichenanzahl voraussagen kann. Gleichzeitig kann man mit UTF-8 im Gegensatz zu Unicode meist annähernd die Hälfte des Speichers sparen, weil Unicode immer 2 Bytes pro Zeichen belegt. Bei UTF-8 kommt es hierzulande seltener vor, dass ein Zeichen mehr als 1 Byte belegt. UTF-8 eignet sich deswegen sehr gut im Texte in Dateien zu speichern, weil dadurch nie zu viel gespeichert wird. Unicode eignet sich im RAM besonders gut, weil man jedes Zeichen direkt ansprechen kann, weil es immer aus 2 Bytes besteht.
Das bringt endlich Licht ins Dunkel was diese Codepages sind. Danke für die Aufklärung.

Aus dem Blickwinkel das mann dann nicht mehr anhand der Speicherverbrauchs sagen kann, wieviele Zeichen überhaupt ein String hat finde ich sehr intressant, so hab ich das noch gar nicht betrachted gehabt.

Also ich hab PB immer im Ascii Modus benutzt (und mich nie um die Schreibmethode gekümmernt, entweder einfach WriteString gemacht oder WriteData) und selbst erstelle Text Dateien und Server Log Auswertungen haben sowieso nur das was Ascii vor kommt.

d.H bleich ich bei solchen Tools einfach bei PB vor 5.50 und schau ob ich mit #PB_Ascii noch ein paar
ms mehr an Speed rausholen kann :mrgreen:
Und jetzt erklär mal genau, was dein Programm tun muss. Ich bin sicher es gibt eine einfache Lösung, auch für dein veraltetes System. Im übrigens sind 1 Mio Zeilen ja nicht mal so viel. Wie lange sind die Zeilen denn überhaupt? Selbst bei 100 Zeichen pro Zeile verbraucht man damit ja nur 200 MB RAM bei Unicode.
Meine Tools sind alle schon seit jahren fertig geschrieben (und auch in Anwendung von mir und Kollegen) für meine Windows PC's, und die Notebooks benutzen sowieso alle nur Debian, und den Stress etwas für Linux umzuschreiben tu ich mir nicht an, selbst sowas banales
wie FileFingeprint mit nem MD5 Flag hat dort unerklärlicherweise nicht funktioniert (PB 5.60, Rückgabewert war immer ein leerer String) obwohl laut install.sh Script alle Abhängigkeiten gepasst haben.

Ich kann nie genau sagen wie lang die Zeilen sind (kommt immer auf den User Agent, die ip usw an) aber wenn mann 1 Million Zeilen auf Zeichenfolgen untersuchen & Filtern lässt, und danach noch Sortiert, und dann mit einer anderen 1 Million Zeilen Log Datei abgleichen lässt auf Dupes, belegt das zum Teil temporär paar 100MB an Ram, selbst unter einem 32 Bit OS, und das Tempo wird dann auch sehr wichtig.

Da wird dann schon mal ausprobiert ob der Abgleich schneller geht, wenn jede Line auf lcase umgewandelt wird, und dann auf dupes abgeglichen

Wie gesagt die Masse an Strings machts, hab eine Proxy Judge laufen, da kommen pro Tag locker 1-2 Milllionen Zugriffe raus :mrgreen: ist eine hervorangende Möglichkeit um an frische Free Proxys zu kommen :)
https://www.geek.com/tech/a-commodore-6 ... s-1672510/
٩(̾●̮̮̃̾•̃̾)۶ __̴ı̴̴̡̡̡ ̡͌l̡̡̡ ̡͌l̡*̡̡ ̴̡ı̴̴̡ ̡̡͡|̲̲̲͡͡͡ ̲▫̲͡ ̲̲̲͡͡π̲̲͡͡ ̲̲͡▫̲̲͡͡ ̲|̡̡̡ ̡ ̴̡ı̴̡̡ ̡͌l̡̡̡̡.___٩(- ̮̮̃-̃)۶
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Verwirrung. Unicode/Asci, wann wo was

Beitrag von NicTheQuick »

Klingt nach nichts aufregendem. Filtern mit einer vorkompilierten RegEx geht ja fix. Dupes finden durch Hashs geht auch in Sekunden, da kann man sogar Purebasics Maps nutzen. Man muss nur die Slots hoch genug ansetzen.
Ich würde auch gar nicht alles in den Speicher laden. Datei öffnen, zeilenweise vorfiltern, hashen und die Hashs mit Offset in der Datei speichern. Zweite Datei öffnen, zeilenweise vorfiltern, hashen und schauen, ob der Hash schon existiert. Falls ja -> Dupe -> Ausgabe, sonst weiter. Und dann liegen nur die Hashs im Speicher, sonst nichts. Danke sequenziellem Festplattencache geht das schnell genug.
Aber vielleicht hab ich dein komplettes Programm auch noch nicht verstanden.

Und falls dein Proxy auf einem Linuxserver läuft, dann nutze einfach grep und uniq. eventuell etwas awk. Das wären wohl meine Hilfsmittel. Ich bin selbst Admin (damit meine ich nicht hier) und muss auch ständig solche Auswertungen von Logs machen.

Ich hatte unter Linux übrigens noch keine Probleme mit den FileFingerprints oder mit der Cypher-Lib allgemein.
Bild
Benutzeravatar
GlassJoe
Beiträge: 108
Registriert: 11.06.2017 20:25
Computerausstattung: 2 x AMD Phenom II x4 945,2x Dell Latitude X300, Dell Latitude D410, Hp Compaq NC4400

Re: Verwirrung. Unicode/Asci, wann wo was

Beitrag von GlassJoe »

NicTheQuick hat geschrieben:Klingt nach nichts aufregendem. Filtern mit einer vorkompilierten RegEx geht ja fix. Dupes finden durch Hashs geht auch in Sekunden, da kann man sogar Purebasics Maps nutzen. Man muss nur die Slots hoch genug ansetzen.
Ich würde auch gar nicht alles in den Speicher laden. Datei öffnen, zeilenweise vorfiltern, hashen und die Hashs mit Offset in der Datei speichern. Zweite Datei öffnen, zeilenweise vorfiltern, hashen und schauen, ob der Hash schon existiert. Falls ja -> Dupe -> Ausgabe, sonst weiter. Und dann liegen nur die Hashs im Speicher, sonst nichts. Danke sequenziellem Festplattencache geht das schnell genug.
Aber vielleicht hab ich dein komplettes Programm auch noch nicht verstanden.

Ich hatte unter Linux übrigens noch keine Probleme mit den FileFingerprints oder mit der Cypher-Lib allgemein.
Also das Dupe filtern wenn die Liste erträglich groß ist mach ich so.

Alles in eine linkedlist einlesen lassen, dann Sortieren von a-z, und dann eine ForEach Schleife, die erst auf String Länge abgleicht, und wenn die gleich ist (ist schneller und wird verhindert wird, daß aa als Dupe von Blaa ausgegeben wird) per FindString den Search String (Proxy IP) suchen,falls dupe, raus damit.

Ist die schnellste mir bekannte Methode.

Beim Abgleich von 2 verschiedenen Listen (wenn sie sehr groß sind, und ich auf den Ram Verbrauch achten muss) mach ich das so.

Liste A einlesen, lines nach Anfangszeichen in einzelne Dateien aufsplitten.
Also 0 in 0.txt 1 in 1.txt usw
dann jede .txt Datei auf Dupes Filtern (mit der Methode oben) danach jede .txt Datei mit List B .txt split Dateien auf Dupes abgleichen.

Also 0.txt von ListA mit 0.txt von ListB usw

Deine Methode finde ich interessant, verstehe sie nur nicht (Maps ? Hab ich in 12 Jahren nie benutzt :) ) wie soll ich auf Dupes filtern ohne das es ewig dauert, wenn etwas nicht schon sortiert ist ?

Sagen wir mal

200.195.190.2 ist in Line 1, und der erste Dupe davon in Line 400.000, dann sind 399.999 Durchgänge nötig bis der erste Dupe gefunden wird.
https://www.geek.com/tech/a-commodore-6 ... s-1672510/
٩(̾●̮̮̃̾•̃̾)۶ __̴ı̴̴̡̡̡ ̡͌l̡̡̡ ̡͌l̡*̡̡ ̴̡ı̴̴̡ ̡̡͡|̲̲̲͡͡͡ ̲▫̲͡ ̲̲̲͡͡π̲̲͡͡ ̲̲͡▫̲̲͡͡ ̲|̡̡̡ ̡ ̴̡ı̴̡̡ ̡͌l̡̡̡̡.___٩(- ̮̮̃-̃)۶
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Verwirrung. Unicode/Asci, wann wo was

Beitrag von NicTheQuick »

Wie sieht denn so eine Zeile aus und wann ist sie für dich eine Dublette?
Bild
Benutzeravatar
GlassJoe
Beiträge: 108
Registriert: 11.06.2017 20:25
Computerausstattung: 2 x AMD Phenom II x4 945,2x Dell Latitude X300, Dell Latitude D410, Hp Compaq NC4400

Re: Verwirrung. Unicode/Asci, wann wo was

Beitrag von GlassJoe »

NicTheQuick hat geschrieben:Wie sieht denn so eine Zeile aus und wann ist sie für dich eine Dublette?

z.B so

Code: Alles auswählen

201.111.140.200 - - [15/Feb/2017:05:06:25 +0300] "GET /mo/azenv.php HTTP/1.0" 200 512 "http:// google.com" "Mozilla/5.0 (X11; U; Linux i686; de-DE;rv:1.7.5)"

201.111.140.210 - - [15/Feb/2017:05:06:26 +0300] "GET /mo/azenv.php HTTP/1.0" 200 512 "http:// google.com" "Mozilla/5.0 (X11; U; Linux i686; de-DE;rv:1.7.5)"

Für mich ist es ein Dupe, wenn die IP Range vorne die selbe ist.
Behalten wird immer die IP mit der kleineren Zahl hinten, in dem Fall also 200
https://www.geek.com/tech/a-commodore-6 ... s-1672510/
٩(̾●̮̮̃̾•̃̾)۶ __̴ı̴̴̡̡̡ ̡͌l̡̡̡ ̡͌l̡*̡̡ ̴̡ı̴̴̡ ̡̡͡|̲̲̲͡͡͡ ̲▫̲͡ ̲̲̲͡͡π̲̲͡͡ ̲̲͡▫̲̲͡͡ ̲|̡̡̡ ̡ ̴̡ı̴̡̡ ̡͌l̡̡̡̡.___٩(- ̮̮̃-̃)۶
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Verwirrung. Unicode/Asci, wann wo was

Beitrag von NicTheQuick »

Also im Endeffekt interessieren dich nur die IPs? Das wäre mein Ansatz:

Code: Alles auswählen

EnableExplicit

Procedure scanFile(file.s, Map ips.i())
	Protected fileId.i, line.s
	Protected regex_ipv4.i, classC.s, suffix.a, found.i
	
	Protected doubles.i = 0, lines.i = 0, errors.i = 0
	
	fileId = ReadFile(#PB_Any, file)
	If Not fileId
		ProcedureReturn #False
	EndIf
	
	; RegEx, die die IPv4 Adresse am Beginn der Zeile erkennt und in class C Bereich und Suffix aufteilt
	regex_ipv4 = CreateRegularExpression(#PB_Any, "^([0-9]+\.[0-9]+\.[0-9]+)\.([0-9]+)", #PB_RegularExpression_MultiLine)
	
	While Not Eof(fileId)
		; Lese zeilenweise
    	line = ReadString(fileId)
    	lines + 1
    	found = #False
    	
    	; Versuche das Muster zu finden
    	If ExamineRegularExpression(regex_ipv4, line)
    		If NextRegularExpressionMatch(regex_ipv4)
    			; Extrahiere die beiden Gruppen
    			classC = RegularExpressionGroup(regex_ipv4, 1)
    			suffix = Val(RegularExpressionGroup(regex_ipv4, 2))
    			found = #True
    		EndIf
    	EndIf
    	
    	; Es wurde was gefunden
    	If found
    	
    		; Wenn das class C Netz bereits existiert
    		If FindMapElement(ips(), classC)
    		
    			; Wenn der bisher gespeicherte Suffix größer als der neue ist
    			If ips(classC) > suffix
    				ips(classC) = suffix
    				
    				doubles + 1
    			EndIf
    		
    		; Wenn es noch nicht existiert, lege es an
    		Else
    			ips(classC) = suffix
    		EndIf
    	
    	; Es wurde nichts gefunden, möglicherweise wegen IPv6-Adressen oder falsch
    	; formatierter Eingabedaten
    	Else
    		errors + 1
    	EndIf
    Wend
    
    ips("doubles") + doubles
    ips("errors") + errors
    ips("lines") + lines
    
    CloseFile(fileId)
    FreeRegularExpression(regex_ipv4)
EndProcedure

NewMap ips.i(100000)

Define time.i = ElapsedMilliseconds()

scanFile("/home/nicolas/tmp/purebasic/access/test.log", ips())
scanFile("/home/nicolas/tmp/purebasic/access/test2.log", ips())

time = ElapsedMilliseconds() - time

Define stats.s = ""

stats + "Vergangene Zeit: " + time + ~" ms\n"
stats + "Eingelesene Zeilen: " + ips("lines") + ~"\n"
stats + "Gefundene class C Adressen: " + Str(MapSize(ips()) + ips("doubles")) + ~"\n"
stats + "Davon Dubletten: " + ips("doubles") + ~"\n"
stats + "Nicht erkannte Zeilen: " + ips("errors") + ~"\n"
stats + ~"\n\"Ja\" klicken um alle " + MapSize(ips()) + " Adressen im Debugfenster auszugeben."

If MessageRequester("Stats", stats, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
	ForEach ips()
		Debug MapKey(ips()) + "." + ips()
	Next
EndIf

SetClipboardText(stats)

In Zeile 70 und 71 sind meine zwei Testdateien, die ich einlese. Die haben insgesamt nur 384890 Zeilen und in einer davon sind jede Menge IPv6-Adressen, die ich ignoriere.
Das ist dann meine Ausgabe:
Vergangene Zeit: 2310 ms
Eingelesene Zeilen: 384890
Gefundene class C Adressen: 10258
Davon Dubletten: 1408
Nicht erkannte Zeilen: 25626
Bild
Benutzeravatar
GlassJoe
Beiträge: 108
Registriert: 11.06.2017 20:25
Computerausstattung: 2 x AMD Phenom II x4 945,2x Dell Latitude X300, Dell Latitude D410, Hp Compaq NC4400

Re: Verwirrung. Unicode/Asci, wann wo was

Beitrag von GlassJoe »

NicTheQuick hat geschrieben:Also im Endeffekt interessieren dich nur die IPs? Das wäre mein Ansatz:

Code: Alles auswählen

EnableExplicit

Procedure scanFile(file.s, Map ips.i())
	Protected fileId.i, line.s
	Protected regex_ipv4.i, classC.s, suffix.a, found.i
	
	Protected doubles.i = 0, lines.i = 0, errors.i = 0
	
	fileId = ReadFile(#PB_Any, file)
	If Not fileId
		ProcedureReturn #False
	EndIf
	
	; RegEx, die die IPv4 Adresse am Beginn der Zeile erkennt und in class C Bereich und Suffix aufteilt
	regex_ipv4 = CreateRegularExpression(#PB_Any, "^([0-9]+\.[0-9]+\.[0-9]+)\.([0-9]+)", #PB_RegularExpression_MultiLine)
	
	While Not Eof(fileId)
		; Lese zeilenweise
    	line = ReadString(fileId)
    	lines + 1
    	found = #False
    	
    	; Versuche das Muster zu finden
    	If ExamineRegularExpression(regex_ipv4, line)
    		If NextRegularExpressionMatch(regex_ipv4)
    			; Extrahiere die beiden Gruppen
    			classC = RegularExpressionGroup(regex_ipv4, 1)
    			suffix = Val(RegularExpressionGroup(regex_ipv4, 2))
    			found = #True
    		EndIf
    	EndIf
    	
    	; Es wurde was gefunden
    	If found
    	
    		; Wenn das class C Netz bereits existiert
    		If FindMapElement(ips(), classC)
    		
    			; Wenn der bisher gespeicherte Suffix größer als der neue ist
    			If ips(classC) > suffix
    				ips(classC) = suffix
    				
    				doubles + 1
    			EndIf
    		
    		; Wenn es noch nicht existiert, lege es an
    		Else
    			ips(classC) = suffix
    		EndIf
    	
    	; Es wurde nichts gefunden, möglicherweise wegen IPv6-Adressen oder falsch
    	; formatierter Eingabedaten
    	Else
    		errors + 1
    	EndIf
    Wend
    
    ips("doubles") + doubles
    ips("errors") + errors
    ips("lines") + lines
    
    CloseFile(fileId)
    FreeRegularExpression(regex_ipv4)
EndProcedure

NewMap ips.i(100000)

Define time.i = ElapsedMilliseconds()

scanFile("/home/nicolas/tmp/purebasic/access/test.log", ips())
scanFile("/home/nicolas/tmp/purebasic/access/test2.log", ips())

time = ElapsedMilliseconds() - time

Define stats.s = ""

stats + "Vergangene Zeit: " + time + ~" ms\n"
stats + "Eingelesene Zeilen: " + ips("lines") + ~"\n"
stats + "Gefundene class C Adressen: " + Str(MapSize(ips()) + ips("doubles")) + ~"\n"
stats + "Davon Dubletten: " + ips("doubles") + ~"\n"
stats + "Nicht erkannte Zeilen: " + ips("errors") + ~"\n"
stats + ~"\n\"Ja\" klicken um alle " + MapSize(ips()) + " Adressen im Debugfenster auszugeben."

If MessageRequester("Stats", stats, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
	ForEach ips()
		Debug MapKey(ips()) + "." + ips()
	Next
EndIf

SetClipboardText(stats)

In Zeile 70 und 71 sind meine zwei Testdateien, die ich einlese. Die haben insgesamt nur 384890 Zeilen und in einer davon sind jede Menge IPv6-Adressen, die ich ignoriere.
Das ist dann meine Ausgabe:
Vergangene Zeit: 2310 ms
Eingelesene Zeilen: 384890
Gefundene class C Adressen: 10258
Davon Dubletten: 1408
Nicht erkannte Zeilen: 25626
Heilige Scheiße dein Code ist echt schnell :shock: (und sehr gründlich :allright: ) ich dachte ich bin schon am Limit, weil ich jeden erdenklichen Trick benutzt hab und so viel herum experimentiert.

Trotzdem ist mein Code minimal schneller, weil ich mit allen faulen Tricks gearbeitet hab :lol:
und nicht so genau prüfe und weniger Auswerte, und wirklich ewig rumneschraubt hab :lol:
und 3 verschiedene vorgehensweisen probiert hab, bis ich den endlich genau so schnell b.z.w schneller hatte

Selbst sowas macht fast 200ms Unterschied aus

Code: Alles auswählen

      x$ = StringField(ReadString(0),1," -")
ist 200-300ms schneller als

Code: Alles auswählen

      x$ = ReadString(0)
      x$ = StringField(x$,1," -")
Mein Code macht es in 3375ms-3400ms (PB 5.24LTS in jaPBe, alle Flags aus)
Deiner in 3413-3422 (PB5.42 im normalen Editor, auch alle Flags aus)

Aber PB5.24LTS scheint wesentlich schneller bei sowas zu sein als 5.42 ! Denn wenn ich meinen
Code in 5.42 schmeise brauch ich 3704-3721ms und das Blatt wendet sich :mrgreen:

Hättest du genau so schlampig gearbeitet wie ich :mrgreen: währe dein Code garantiert im 2,5 bis 2,8 Sek Bereich

Mein Testfile ist 126Mb Gross

Hier der Code (3 Variationen sind drin, nur die 3 ist an)

Code: Alles auswählen

  ; 0 = Ascending
  ; 1 = Descending
  ; 2 = No Case
  ; 2 = NoCase|Ascending -> because No Case use Ascending as Default
  ; 3 = NoCase|Descending
  ; Speicherverbrauch ist der selbe ! Egal ob 0 oder 2
  
  ; 0 Ascending ist 30% schneller als 2
  ; Ein Thread für je eine Liste mit 2 NoCase geht nicht, scheint ein Bug zu sein, wird nur eine Liste sortiert
  
  ; Schnellstmöglicher Code (0 Ascending), alles getestet, schneller geht es nicht
  
  ;/ ACHTUNG NICHT For tmp_p = 0 To ListSize(TH1.s()) -1  benutzen, führt unter umständen zu Problemen (hatte welche)
  ;/ stattdessen tmp_max = ListSize(TH1.s()) benutzen und dann For tmp_p = 0 To tmp_max -1
  
  Global NewList TH1.s() 
  Global time
  
  Procedure DuppeKill()
    tmp_max = ListSize(TH1.s()) : SortList(TH1.s(),#PB_Sort_Ascending)
    FirstElement(TH1.s()) : blabla_1$ = TH1.s() : len1=Len(blabla_1$)
    NextElement(TH1.s()) : blabla_2$ = TH1.s() : len2=Len(blabla_2$) 
    For tmp_p = 0 To tmp_max -1 
      If len1=len2 
        If FindString(blabla_1$,blabla_2$,1) = 1
          DeleteElement(TH1.s())
          Debug "DEL => A="+blabla_1$+" B="+blabla_2$ 
          dupes +1
        Else
          nodupe +1
        EndIf
      Else
        nodupe +1
      EndIf 
      blabla_1$ = TH1.s() : len1=Len(blabla_1$) 
      If NextElement(TH1.s()) = 0
        Break
      EndIf 
      blabla_2$ = TH1.s() : len2=Len(blabla_2$) 
    Next 
    ForEach TH1.s()
      Debug TH1.s()
    Next
    time = ElapsedMilliseconds() - time
    MessageRequester("",Str(dupes)+" | "+Str(nodupe)+" | "+Str(time),#MB_OK) 
  EndProcedure 
 
  time = ElapsedMilliseconds()
  
  If ReadFile(0,"C:\999\access_log")
    While Eof(0) = 0
      x$ = StringField(ReadString(0),1," -")
      If CountString(x$,".") = 3
        
        ; ;/ 3655ms-3669ms | VARIATION 1
        ; a$ = StringField(x$,1,".")
        ; b$ = StringField(x$,2,".")
        ; c$ = StringField(x$,3,".")
        ; x$ = a$+"."+b$+"."+c$
        ; ;/
        
        
        ; ;/ 3406ms - 3412ms | VARIATION 2
        ; Pos = 0
        ; For xx = 1 To 3
          ; Pos = FindString(x$,".",Pos+1)
        ; Next
        ; x$=Left(x$,Pos-1)
        ; ;/
       
        
        ;/ 3375ms - 3400ms | VARIATION 3
        Pos = 5
        For xx = 0 To 1
          Pos = FindString(x$,".",Pos+1)
          If Pos
            bak = Pos
          Else
            Pos = bak
          EndIf
        Next
        x$=Left(x$,Pos-1) 
        ;/
        
        
        AddElement(TH1())
        TH1() = x$
        
      EndIf 
      
    Wend
    
    CloseFile(0)
    DuppeKill() 
  EndIf
 
Hab viele kleine Dirty Tricks angewendet, die kürzeste IP die möglich ist, währe
1.1.1.1 also hab ich FindString bei 6 anfangen lassen usw :mrgreen:

Ich werde mir deinen Code speichern, und mich auf jeden Fall mal in dieses Maps einarbeiten.
Danke für den coolen Code :allright: :allright: :allright: :allright:
https://www.geek.com/tech/a-commodore-6 ... s-1672510/
٩(̾●̮̮̃̾•̃̾)۶ __̴ı̴̴̡̡̡ ̡͌l̡̡̡ ̡͌l̡*̡̡ ̴̡ı̴̴̡ ̡̡͡|̲̲̲͡͡͡ ̲▫̲͡ ̲̲̲͡͡π̲̲͡͡ ̲̲͡▫̲̲͡͡ ̲|̡̡̡ ̡ ̴̡ı̴̡̡ ̡͌l̡̡̡̡.___٩(- ̮̮̃-̃)۶
Antworten