Seite 1 von 1

Umlaute-Problem beim Verzeichnis per DIR einlesen

Verfasst: 11.08.2023 14:12
von bin_neu_hier
Hallo Leute,

ich würde gerne Verzeichnisse per DIR-Befehl einlesen. Sieht ungefähr so aus:

Code: Alles auswählen

compstring$ = "/c dir "
compstring$ + #DQUOTE$ + GetGadgetText(sg1) + #DQUOTE$ ; Verzeichnis
compstring$ + GetGadgetText(sg2) + " "   ;Suchmaske wie z. B. "*.p*"
;evtl. weitere Parameter für Attribute etc.
compstring$ + "/s /b"   ;inkl. Unterverzeichnisse und Format der Ausgabe

err = RunProgram(GetEnvironmentVariable("COMSPEC"),compstring$,"", #PB_Program_Open | #PB_Program_Read | #PB_Program_Hide | #PB_Program_UTF8)
            ClearList(foundfiles$())
            If err
              While ProgramRunning(err)
                If AvailableProgramOutput(err)                  
                  AddElement(foundfiles$())
                  foundfiles$() = ReadProgramString(err)
                EndIf
              Wend
              CloseProgram(err)
            EndIf
..., weil ich die Wildcard-Suche per DIR-Befehl so praktisch finde. Der Haken an der Sache ist, dass Dateinamen mit Umlauten falsch eingelesen werden, ä und ö werden durch "Chinesen" ersetzt, das ü verschwindet komplett, ...

Habe schon mit #PB_Program_UTF8 bzw. #PB_Program_ASCII rumexperimentiert oder mit CharToOem_ oder OemToChar_, hab's aber nicht hingekriegt. Kann mich da jemand kräftig in die richtige Richtung schubsen? Oder ist das eh' sowas wie ein totes Pferd reiten wollen?

Re: Umlaute-Problem beim Verzeichnis per DIR einlesen

Verfasst: 11.08.2023 16:17
von Macros
Bei grad daheim angekommen und habe daher kein Windows zur Hand um das nachzuvollziehen.

Aber... aus deiner Beschreibung weiß ich noch nicht weshalb du den dir-Befehl nutzen willst.
Examinedirectory kann Patterns und spart dir einerseits das herumhantieren mit der API, andererseits läuft dein Code dann auch unter Linux und Max.

Du könntest auch die Einträge mit einer RegEx filtern und hast noch viel mehr Möglichkeiten.

Die Übung Programmausgaben zu lesen schadet trotzdem nie :wink:

Falls du auch rekursiv arbeiten willst, geht das mit Rekursion im Programm.
Sehr ausführlich hier: https://github.com/SicroAtGit/PB-CodeAr ... ntries.pbi

oder kurz und knackig hier:

Code: Alles auswählen

EnableExplicit
Define directory$="Pfad"
Define pattern$="*.*"

Procedure.s ListDir(path$,pattern$, lenbasedir=0)
  Define dir, name$, out$
  If lenbasedir=0
    lenbasedir=Len(path$)+1
  EndIf
  
  dir = ExamineDirectory(#PB_Any,path$,pattern$)
  If dir
    While NextDirectoryEntry(dir)
      name$=DirectoryEntryName(dir)

      If name$="." Or name$=".."
        Continue ; So kommen wir in keine Endlosschleife
      EndIf
    
      ; Wir schneiden den ursprünglichen Pfad mit mid() ab
      out$+Mid(path$,lenbasedir)+DirectoryEntryName(dir)+#LF$ 
      If DirectoryEntryType(dir)=#PB_DirectoryEntry_Directory
        out$+ListDir(path$+DirectoryEntryName(dir)+"/",pattern$,lenbasedir)
      EndIf
    Wend
    FinishDirectory(dir)
  EndIf

  ProcedureReturn out$
EndProcedure

Debug ListDir(directory$,pattern$)
Für Windows kannst du die Forward Slashes "/" in Backward Slashes "\" ändern, damit die Pfade normaler aussehen.

Re: Umlaute-Problem beim Verzeichnis per DIR einlesen

Verfasst: 11.08.2023 17:22
von HeX0R
Du kannst auch /U hinzufügen, dann sollte der output von COMSPEC Unicode sein (nicht! UTF-8!)

Re: Umlaute-Problem beim Verzeichnis per DIR einlesen

Verfasst: 12.08.2023 02:51
von bin_neu_hier
Hallo Macros und Hexor!

Warum den DIR-Befehl? Habe eine ganze Reihe von Code-Beispielen hier und im englischen Forum ausprobiert. Warum auch immer, in vielen Beispielen wollte die Auswahl der Suchmaske (z. B. "*.p*") nicht funktionieren. Es ist immer wieder darauf hinausgelaufen, erstmal alle Dateien in eine Liste zu laden, um dann auszusortieren. Bin irgendwann über die Möglichkeit gestolpert, über den DIR-Befehl die Daten abzurufen - hat mir gefallen, wollte dabei bleiben. Ja, rekursive Dateisuche wäre wünschenswert, habe aber nichts Brauchbares gefunden, dass einerseits das kann, was ich brauche, andererseits auch von mir verstanden wird. Das wirklich ausführliche Beispiel https://github.com/SicroAtGit/PB-CodeAr ... ntries.pbi geht weit über meinen Anfängerhorizont hinaus. Wenn ich den Code nicht verstehe, kann ich den auch nicht an meine Bedürfnisse anpassen. Soll nicht heißen, dass ich nicht bereit wäre, mich in Dinge hineinzufuchsen, aber die Umstände lassen nicht das eingehende Studium zu, das erforderlich wäre. Ich werde nie über ein Anfängerstadium hinauskommen und für mich ist das auch OK. Wie andere Anfänger auch profitiere ich davon, dass die Profis in Foren wie diesem ihr Fachwissen zur Verfügung stellen. Herzlichen Dank an alle!

@ Hexor: Dein Tipp mit "/U" funzt bestens zusammen mit dem "#PB_Program_Unicode"-Flag bei RunProgram. Besten Dank!

Re: Umlaute-Problem beim Verzeichnis per DIR einlesen

Verfasst: 12.08.2023 07:42
von H.Brill
Oder laß es doch gleich mit DIR mittels Umleitung in eine Datei schreiben :
dir "*.p*" /s >dateien.txt
/s bezieht alle Unterordner mit ein.
Da in dateien.txt ja noch mehr drin steht, brauchst du ja nur (am besten mit regex)
die Dateinamen rausfiltern. Das sind alle Zeilen der dateien.txt, die mit Datum und Zeit
anfangen (16 Zeichen). Der Rest ist ja dann einfach.

Re: Umlaute-Problem beim Verzeichnis per DIR einlesen

Verfasst: 13.08.2023 09:17
von bin_neu_hier
Hallo Leute,

hilft ja alles nix, Macros' Argumente sind nicht von der Hand zu weisen. Habe rumgesucht und einen Code gefunden, den ich inhaltlich einigermaßen verstehe und bei dem ich mir zutraue, die eine oder andere erforderliche Anpassung hinzubekommen. Nämlich den hier:
http://forums.purebasic.com/english/vi ... p?t=24887

Code: Alles auswählen

Procedure SearchDirectory(dir$, pattern$, List dList.s(), level.l = 0)
  Protected eName$
  NewList Dirs.s()
  
  If (level = 0)
    ClearList(dList())
  EndIf
  
  If Right(dir$, 1) <> "\"
    dir$ + "\"
  EndIf
  
  If ExamineDirectory(0, dir$, "")
    While NextDirectoryEntry(0)
      If DirectoryEntryType(0) = #PB_DirectoryEntry_Directory
        eName$ = DirectoryEntryName(0)
        If (eName$ <> ".") And (eName$ <> "..")
          AddElement(Dirs())
          Dirs() = eName$ + "\"
        EndIf
      EndIf
    Wend
    FinishDirectory(0)
   
    If ExamineDirectory(0, dir$, pattern$)
      While NextDirectoryEntry(0)
        eName$ = DirectoryEntryName(0)
        If (eName$ <> ".") And (eName$ <> "..")
          AddElement(dList())
          dList() = dir$ + eName$
          If DirectoryEntryType(0) = #PB_DirectoryEntry_Directory
            dList() + "\"
          EndIf
        EndIf
      Wend
      FinishDirectory(0)
    EndIf
  EndIf
 
  If ListSize(Dirs())
    ForEach Dirs()
      SearchDirectory(dir$ + Dirs(), pattern$, dList(), level + 1)
    Next
  EndIf
 
  If (level = 0)
    ForEach dList()
      dList() = Mid(dList(), Len(dir$) + 1, Len(dList()))
    Next
    SortList(dList(), 2)
  EndIf
EndProcedure

NewList FilesAndFolders.s()
SearchDirectory("C:\WINDOWS", "sys*", FilesAndFolders())
Debug "Found " + Str(ListSize(FilesAndFolders())) + " object(s)"
ForEach FilesAndFolders()
  Debug FilesAndFolders()
Next
End
Wenn ein User als Laufwerk "C:\" angibt und als Suchmaske "*.*", dann rödelt die Maschine u. U. eine quälend lange Zeit, bis alles gefunden wurde. Ich brauche also so etwas wie einen "Not-Ausschalter". Habe aber nur eine viel zu vage Vorstellung davon, wie das mit den Events abläuft.
Wenn ich einen Button hätte, der eine (globale) Variable entsprechend setzt und bei jedem neu gefundenen Unterverzeichnis diese Variable abgefragt werden würde, würde das funktionieren? Oder wird der Buttonklick erst bearbeitet, wenn die Routine fertig abgearbeitet ist? Würde man mit einen "kleinen" Delay Zeit für die Eventabfrage schaffen, ohne die Suchroutine zu sehr zu verzögern?

Re: Umlaute-Problem beim Verzeichnis per DIR einlesen

Verfasst: 13.08.2023 09:41
von H.Brill
Ich würde die Suche dann in einem Thread laufen lassen.

Re: Umlaute-Problem beim Verzeichnis per DIR einlesen

Verfasst: 13.08.2023 11:49
von mk-soft
Siehe Beispiel 4 von
Link: Mini Thread Control
Um es noch etwas Schneller zu machen, kannst du im MyThreadGetFiles das Delay von 5 ms auf 1 ms umstellen.

Eine deutsche Beschreibung von Mini Thread Control (Ohne Beispiel 4) findest du hier: viewtopic.php?t=31581

Re: Umlaute-Problem beim Verzeichnis per DIR einlesen

Verfasst: 14.08.2023 15:09
von Axolotl
Moin,
also als "Not-Ausschalter" würde ich meine Vorschläge nicht bezeichnen, aber man kann durch einfachen Tastendruck beliebige Schleifen verlassen.
Einfach den Dreizeiler innerhalb eine Schleife "richtig" einbauen. (Windows only)

Code: Alles auswählen

  
If GetAsyncKeyState_(#VK_ESCAPE) & $8000 
  Break ; get out -- escape the loop  
EndIf 

Je nachdem wie "professionel" die App aussehen soll, kann auch ein Button als Schleifen-Abbruch eingebaut werden....
Ich habe dafür mal eine häufig gesehene/verwendete "FlushMessages()" procedure erweitert.

Code: Alles auswählen

Procedure FlushMessages(Gadget = 0) 
  While WindowEvent() 
    If IsGadget(Gadget) And EventGadget() = Gadget
      ProcedureReturn #True 
    EndIf 
  Wend  
  ProcedureReturn #False 
EndProcedure 
Du solltest allerdings bedenken, dass du hiermit die Nachrichtenschlange von Windows abfragst und alle Nachrichten, die nicht dem Gadget entsprechen verloren gehen. D.h. diese Nachrichten tauchen nicht mehr in der Hauptschleife auf.
Für die "professionelle Version" haben die Pros ja schon die Thread Lösungen ins Spiel gebracht.