Forum: PC-Programmierung opendir(), readdir() Sortierung


von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Nur mal eine Frage:

Wenn ich mit readdir() mir alle Verzeichnisse bzw Dateien
auflisten lasse erscheinen die aufsteigend nach Name.

Ist das so korrekt bzw. kann ich die Sortierung irgendwie
beeinflussen ?

(Win 7, C)

von (prx) A. K. (prx)


Lesenswert?

Seiten des API ist keine Reihenfolge definiert. Sie hängt also vom 
Filesystem ab. Das kann bei NTFS anders aussehen als bei FAT.

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Danke.

Also doch Einlesen und dann qsort ;)

von georg (Gast)


Lesenswert?

Joachim D. schrieb:
> erscheinen die aufsteigend nach Name.

Wahrscheinlich wurden sie in dieser Reihenfolge reinkopiert. Wenn du 
genaueres wissen willst kopier noch eine rein, die mit A anfängt, und 
schau nach ob sie am Anfang oder am Ende steht.

Abgesehen davon: entweder das API sagt ausdrücklich, dass die 
Reihenfolge sortiert ist und wie, oder man muss selbst sortieren.

Dass es eine "physikalische" Reihenfolge gibt, ist aus dem Bewusstsein 
geraten, da die nirgends mehr angezeigt wird. Meines Wissens bietet der 
Windows-Explorer garkeine unsortierte Anzeige an, auch DIR nicht, 
jedenfalls ist sortiert Voreinstellung.

Georg

von (prx) A. K. (prx)


Lesenswert?

Filesystem wie NTFS mit innerer Baumstruktur haben ein inhärentes 
Sortierverhalten, was aber der internen Zeichencodierung folgt, nicht 
der je nach Sprache grammatikalisch gewünschten. Andere Filesysteme wie 
FAT speichern völlig unsortiert.

: Bearbeitet durch User
von Dr. Sommer (Gast)


Lesenswert?

Joachim D. schrieb:
> Also doch Einlesen und dann qsort ;)

Da gibt's doch ne elegante Möglichkeit... :-)
1
#include <iostream>
2
#include <filesystem>
3
#include <vector>
4
#include <string>
5
#include <iterator>
6
#include <algorithm>
7
8
int main () {
9
  std::vector<std::string> files;
10
  std::transform (std::filesystem::directory_iterator("/home"), std::filesystem::directory_iterator(), std::back_inserter (files), [] (auto& e) { return e.path (); } );
11
  std::sort (files.begin (), files.end ());
12
  
13
  std::copy (files.begin (), files.end (), std::ostream_iterator<std::string> (std::cout, "\n"));
14
  std::cout << std::endl;
15
}

Kompilieren / linken mit -lstdc++fs -std=c++17

von imonbln (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Da gibt's doch ne elegante Möglichkeit... :-)

Außer das der TO nach Win7 und C gefragt hat.

Warum muss eigentlich jeder Thread hier dar nach C Fragt damit enden das 
irgendwer mit C++ um die Ecke kommt?

Ja C++ ist eine schöne Mächtige Sprache und wenn man die Wahl hat sollte 
man C++ nehmen, aber die Wahl hat nicht jeder vielleicht ist der TO in 
einen Legacy Projekt, oder es gibt Vertrags rechtliche gründe C zu 
nehmen und schon ist die Lösung nicht mehr elegant.

von Dr. Sommer (Gast)


Lesenswert?

imonbln schrieb:
> Außer das der TO nach Win7 und C gefragt hat.

Das geht auch unter Win7. Und die meisten C-Compiler liefern auch 
C++-Compiler mit. Vielleicht kompiliert er ja sogar unwissenderweise mit 
C++, da z.B. die C-Unterstützung von MSVC nicht so dolle ist. Und 
vielleicht hat er ja Interesse daran, das Programm kompakter zu machen. 
Und vielleicht interessiert es ja auch andere Leser.

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Ich kompiliere wissenderweise mit einem C-Compiler. Mit C++
habe ich bis jetzt ein Projekt mit dem Gnu-Compiler durchgezogen.

Der C-Code zum Laden eines Verzeichnisses mit anschließendem
Sortieren ist auch nicht "größer" wie das C++-Bespiel.

C ist erheblich weniger Tipparbeit.

von Dr. Sommer (Gast)


Lesenswert?

Joachim D. schrieb:
> C ist erheblich weniger Tipparbeit.

Hm, echt? Wie schaffst du das? Ich komm in C auf die doppelte Anzahl 
Zeichen:
1
#include <sys/types.h>
2
#include <dirent.h>
3
#include <stdlib.h>
4
#include <stdio.h>
5
#include <string.h>
6
7
int cmp (const void* a, const void* b) {
8
  return strcmp (a, b);
9
}
10
11
int main () {
12
  DIR* dirHandle = opendir("/home");
13
  if (!dirHandle) return 1;
14
  
15
  int ret = 0;
16
  size_t curSize = 32, read = 0;
17
  char** files = (char**) malloc (sizeof(char*) * curSize);
18
  if (!files) {
19
    ret = 1;
20
    goto closeDir;
21
  }
22
  memset (files, 0, sizeof(char*) * curSize);
23
  
24
  struct dirent* dirEntry;
25
  while ((dirEntry = readdir(dirHandle)) != NULL) {
26
    if (read >= curSize) {
27
      char** newBlock;
28
      curSize *= 2;
29
      if ((newBlock = realloc (files, curSize * sizeof (char*))) == NULL) {
30
        ret = 1;
31
        goto freePaths;
32
      }
33
      files = newBlock;
34
    }
35
    if ((files[read] = strdup (dirEntry->d_name)) == NULL) {
36
      ret = 1;
37
      goto freePaths;
38
    } else {
39
      ++read;
40
    }
41
  }
42
  ret = 0;
43
  qsort (files, read, sizeof (char*), cmp);
44
  
45
  for (size_t i = 0; i < read; ++i) {
46
    puts (files [i]);
47
  }
48
  
49
  freePaths:
50
  for (size_t i = 0; i < read; ++i) free (files [i]);
51
  free (files);
52
  
53
  closeDir:
54
  closedir(dirHandle);
55
  
56
  return ret;
57
}

Mache aber auch nicht mehr viel C. Was gibt's noch für Abkürzungen?

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Na, das mache ich etwas kompakter ;)

von tutut (Gast)


Lesenswert?

Dr. Sommer schrieb:
> int main () {
>   std::vector<std::string> files;
.....

Elegant ist ja was Anderes, alleine vom Äußeren, den ewigen 
Wiederholungen. Trotzdem danke, kann ja sein dass man beruflich mal mit 
dem Rotz zu tun bekommt dann ist man schon abgehärtet.

: Wiederhergestellt durch Moderator
von tutut (Gast)


Lesenswert?

@Sommer Also das liegt nicht an dir, ist auch meine persönliche Meinung, 
aber recht viel hässlicher kann eine Programmiersprache nicht sein mit 
ewigen Pfaden zu irgendwelchen Libraries mit tausend Sonderzeichen, die 
stechen förmlich ins Auge.

von Dr. Sommer (Gast)


Lesenswert?

tutut schrieb:
> Also das liegt nicht an dir, ist auch meine persönliche Meinung, aber
> recht viel hässlicher kann eine Programmiersprache nicht sein mit ewigen
> Pfaden zu irgendwelchen Libraries

Wenn das dein Hauptproblem ist, schreib einfach "using std::string;" 
etc. Ist letztlich in vielen Sprachen so außer C, wo alle Bezeichner 
aller Bibliotheken im selben Namespace sind und kollidieren können.

von Dr. Sommer (Gast)


Lesenswert?

Joachim D. schrieb:
> Na, das mache ich etwas kompakter ;)

Na, da bin ich gespannt!

So sieht der "Rotz" aus wenn man sich mittels "using" die Bezeichner 
abkürzt:
1
#include <iostream>
2
#include <filesystem>
3
#include <vector>
4
#include <string>
5
#include <iterator>
6
#include <algorithm>
7
8
using std::vector;
9
using std::string;
10
using std::transform;
11
using std::filesystem::directory_iterator;
12
using std::back_inserter;
13
using std::sort;
14
using std::copy;
15
using std::ostream_iterator;
16
using std::cout;
17
18
int main () {
19
  vector<string> files;
20
  transform (directory_iterator ("/home"), directory_iterator (), back_inserter (files), [] (auto& e) { return e.path (); } );
21
  sort (files.begin (), files.end ());
22
  
23
  copy (files.begin (), files.end (), ostream_iterator<string> (cout, "\n"));
24
}

von (prx) A. K. (prx)


Lesenswert?

Also wenn schon kompakter und nicht C, wärs dann damit: ;-)
  print join "\n", sort </home/*>;

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Aber aber, Perl ist doch pöse, wegen seiner schrecklichen Syntax. :-))

von Udo S. (urschmitt)


Lesenswert?

Wie groß sind denn die binaries beider Varianten (also ohne daß jetzt 
wesentliche Teile in ingendwelchen dlls ausgelagert sind)?

von (prx) A. K. (prx)


Lesenswert?

Jörg W. schrieb:
> Aber aber, Perl ist doch pöse, wegen seiner schrecklichen Syntax. :-))

Eben. Genau wie C und C++. :-))

von Rolf M. (rmagnus)


Lesenswert?

Dr. Sommer schrieb:
1
  copy (files.begin (), files.end (), ostream_iterator<string> (cout,  "\n"));

Ich hab immer den Eindruck, dass copy mit ostream_iterator hauptsächlich 
verwendet wird, weil es Leute irgendwie für cool halten, dass man das 
kann. In der Praxis würde ich aber einfach schreiben:
1
for (auto& file: files) cout << file << '\n';

Und ich finde auch, dass statt dem hier:
1
transform (directory_iterator ("/home"), directory_iterator (), back_inserter (files), [] (auto& e) { return e.path (); } );

das folgende vielleicht uncooler, dafür aber kürzer und lesbarer ist:
1
for (auto& e: diretory_iterator("/home")) files.push_back(e.path());

von tutut (Gast)


Lesenswert?

Dr. Sommer schrieb:
> using std::vector;
> using std::string;
> using std ...
...

Danke, schon besser. Tu uns den Gefallen und mach das ab jetzt immer so 
(ich hab des offenen schon deine Beiträge gelesen und nix verstanden)

von Marco H. (damarco)


Lesenswert?

nunja aber die Vergleichsfunktion mit strcmp() hat einen blöden 
Nachteil..

strcmp() vergleicht Zeichenweise und bricht ab beim Ende der 
Zeichenkette oder bei ersten Zeichen das ungleich ist ab und liefert 
größer/kleiner zurück. Es vergleicht plump die Values und berücksichtigt 
nicht der Wertung der Zeichen.

CcAazZ usw.. unter dem Aspekt kommt nicht das gewünschte Ergebnis zu 
Stande wenn man in die ASCII Tabelle schaut...


alphasort (const void *a, const void *b)  schon ob das portable ist weiß 
ich jetzt nicht..

Die Frage ist noch nicht beantwortet :)

: Bearbeitet durch User
von test (Gast)


Lesenswert?

Marco H. schrieb:
> alphasort (const void *a, const void *b)  schon ab das portable ist weiß
> nicht..

Ist das nicht seit 20 Jahren obsolet? Oder verstehe ich das falsch und 
das ist doch voll Unicode kompatibel?

;-)


Ernsthaft, dieses Bytearrygeraffel (Um Strings zu speichern) sollte man 
langsam mal lassen. Programme die intern nicht komplett Unicode nutzen 
sind schon lange nicht mehr zeitgemäß und machen nur Ärger.

von MaWin (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Ich komm in C auf die doppelte Anzahl Zeichen

Kein Wunder, du kannst es auch nicht.

Dr. Sommer schrieb:
> Mache aber auch nicht mehr viel C

Offenkundig mehr in Basic, den gotos und Krückencode nach zu urteilen. 
Wieso else nach goto kommt ist auch zweifelhaft.

Und seit wann man in C eine Deklaration wie "int ret" mitten im Code 
haben darf auch.

von MaWin (Gast)


Lesenswert?

test schrieb:
> Programme die intern nicht komplett Unicode nutzen sind schon lange
> nicht mehr zeitgemäß und machen nur Ärger

Welchen Unicode ? UTF8, UTF16, 16 oder 32 bit wchar_t, big endian oder 
small endian ?

von Dr. Sommer (Gast)


Lesenswert?

MaWin schrieb:
> Kein Wunder, du kannst es auch nicht.

Wer kann das schon richtig.

MaWin schrieb:
> Offenkundig mehr in Basic, den gotos und Krückencode nach zu urteilen.

goto Ist in C halt das was strukturierter Fehler Behandlung am Nächsten 
kommt. Richtige Sprachen haben dafür Exceptions.

MaWin schrieb:
> Wieso else nach goto kommt ist auch zweifelhaft.

} übersehen?

MaWin schrieb:
> Und seit wann man in C eine Deklaration wie "int ret" mitten im Code
> haben darf auch.

Seit 20 Jahren (C99).

von Marco H. (damarco)


Lesenswert?

wollte nur darauf hinweisen das der Sachverhalt nicht so ganz einfach 
ist ;)

Dann strcoll()

https://docs.microsoft.com/de-de/cpp/c-runtime-library/reference/strcoll-wcscoll-mbscoll-strcoll-l-wcscoll-l-mbscoll-l?view=vs-2019

Goto ist aus vielerlei Hinsicht unschön... außer in der Linux Kernel 
Programmierung. Bei Treibern wird es benutzt um bei Fehlern aufzuräumen.

Außerdem gibt es kein Problem was sich nicht ohne Goto lösen lässt.

: Bearbeitet durch User
von test (Gast)


Lesenswert?

MaWin schrieb:
> Welchen Unicode ? UTF8, UTF16, 16 oder 32 bit wchar_t, big endian oder
> small endian ?

Unicode nennt man die verbindliche Zuordnung von Nummern zu 
Symbolbedeutungen.

UTF8 usw. sind Methoden um diese Nummern in einer Bytefolge zu 
speichern. Du vermischt hier also vollkommen unterschiedliche Dinge 
miteinander.

von S. R. (svenska)


Lesenswert?

Das heißt, du willst also den Speicherverbrauch des Programms für 
Strings schlicht vervierfachen und 32-Bit Codepoints speichern. Richtig?

Oder doch lieber UTF8, UTF16BE, UTF16LE oder was anderes nutzen?

von Rolf M. (rmagnus)


Lesenswert?

S. R. schrieb:
> Das heißt, du willst also den Speicherverbrauch des Programms für
> Strings schlicht vervierfachen und 32-Bit Codepoints speichern. Richtig?

Der Speicherverbrauch vervierfacht sich nur, wenn das Programm 
ausschließlich aus Strings besteht und weder irgendwelchen Programmcode, 
noch andere Ressourcen wie z.B. Grafiken enthält. Tatsächlich ist es in 
einigen Sprachen üblich, UCS-4 für Strings zu verwenden.

> Oder doch lieber UTF8, UTF16BE, UTF16LE oder was anderes nutzen?

Dann muss man allerdings zwischen der Länge des Strings im Bezug auf 
Speicher und im Bezug auf Anzahl Zeichen unterscheiden. Man müsste dann 
also entweder jedesmal mühsam die Zahl an Zeichen ausrechnen, wenn man 
sie braucht, oder man müsste beide Werte speichern und bei jeder 
Änderung aktualisieren. Das lohnt sich auf einem aktuellen PC nicht, nur 
um ein paar Dutzend Kilobytes RAM zu sparen.

von test (Gast)


Lesenswert?

S. R. schrieb:
> Das heißt, du willst also den Speicherverbrauch des Programms für
> Strings schlicht vervierfachen und 32-Bit Codepoints speichern. Richtig?

Nur mal so aus Neugier... Was machst du in deinem "ein String ist ja nur 
ein Byte Array" Programm, wenn dein Nutzer z.B. eine Datei mit 
Japanischen Zeichen im Dateinamen hat? Abstürzen lassen oder eine 
Meldung zeigen die den Nutzer auffordert, derartig seltsame Sachen zu 
lassen?

von Dr. Sommer (Gast)


Lesenswert?

Die eigentliche Frage bei Unicode ist doch: Was ist die korrekte 
Reihenfolge von drei Dateien mit den Namen "?", "文件" und "♫"?

Marco H. schrieb:
> Außerdem gibt es kein Problem was sich nicht ohne Goto lösen lässt.

Korrekt, aber für das strukturierte Aufräumen nach Fehlern eignet es 
sich überraschend gut.

Außer Beschimpfungen zu meinem C-Code wurde bisher kein besserer 
gezeigt. Daher gehe ich mal davon aus, dass es doch nicht signifikant 
besser geht.

von test (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Die eigentliche Frage bei Unicode ist doch: Was ist die korrekte
> Reihenfolge von drei Dateien mit den Namen "?", "文件" und "♫"?

Das coole an Unicode ist das uns das komplett egal sein kann. Man ruft 
die Unicode konforme Sortierfunktion auf und gut ist.

Die kümmert sich auch darum so etwas korrekt zu sortieren.
--
A‐B
A.B
A‑B
--

Der erste und der dritte Eintrag dieser Liste sind unterschiedlich (sie 
unterscheiden sich im mittleren Zeichen), aber man möchte sie bei einer 
alphabetischen Sortierung trotzdem als identisch betrachten.

von Dr. Sommer (Gast)


Lesenswert?

test schrieb:
> Man ruft die Unicode konforme Sortierfunktion auf und gut ist.

Die ist dann aber ziemlich komplex. libicu gibt es z.B. dafür.

von test (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Die ist dann aber ziemlich komplex.

Und? Wofür hat man das Betriebssystem auf der Kiste?

Und der Arduino oder das Linux auf dem Toaster darf gerne weiterhin 
8-Bit ASCII nutzen, da hat jeder Verständnis für.

von (prx) A. K. (prx)


Lesenswert?

test schrieb:
> Und der Arduino oder das Linux auf dem Toaster darf gerne weiterhin
> 8-Bit ASCII nutzen, da hat jeder Verständnis für.

Ein ordentlicher Toaster basiert auf BSD und beherrscht 
selbstverständlich moderne Zeichensätze.

von Dr. Sommer (Gast)


Lesenswert?

test schrieb:
> Und? Wofür hat man das Betriebssystem auf der Kiste?

Nix Und, das ist schon gut so. Man sollte aber eben im Hinterkopf 
behalten dass da viel Komplexität drin steckt.

von S. R. (svenska)


Lesenswert?

Rolf M. schrieb:
>> Das heißt, du willst also den Speicherverbrauch des Programms
>> für Strings schlicht vervierfachen und 32-Bit Codepoints speichern.
>> Richtig?
>
> Der Speicherverbrauch vervierfacht sich nur, wenn das Programm
> ausschließlich aus Strings besteht und weder irgendwelchen
> Programmcode, noch andere Ressourcen wie z.B. Grafiken enthält.

Darum schrieb ich "für Strings". Muss ich sowas noch hervorheben oder 
jedesmal einen Vortrag mit allen Details ausarbeitern?

> Tatsächlich ist es in einigen Sprachen üblich,
> UCS-4 für Strings zu verwenden.

Die meisten mir bekannten Sprachen verwenden allerdings utf8.
Die JVM nutzt intern UCS16, kann also ohnehin nur die BMP (Basic 
Multilingual Plane).

test schrieb:
> Nur mal so aus Neugier... Was machst du in deinem "ein String ist
> ja nur ein Byte Array" Programm, wenn dein Nutzer z.B. eine Datei
> mit Japanischen Zeichen im Dateinamen hat?

Nix. Ich gebe die an das Betriebssystem weiter. Warum sollte ich den 
Dateinamen in einen String wandeln wollen? Solange ich da nix rumparsen 
muss, kann mir der Name doch egal sein.

> Abstürzen lassen oder eine Meldung zeigen die den Nutzer
> auffordert, derartig seltsame Sachen zu lassen?

Dazu müsste ich erstmal rauskriegen, dass der Dateiname irgendwie 
seltsam ist. Dafür zusätzlichen Code in mein Programm tun? Nee, danke.

Im Übrigen ist utf8 dafür wesentlich besser geeignet als UCS32. 
Platzsparender für fast alle relevanten Anwendungsfälle sowieso.

von Dr. Sommer (Gast)


Lesenswert?

S. R. schrieb:
> Solange ich da nix rumparsen
> muss, kann mir der Name doch egal sein.

Zum Sortieren muss man das aber, wofür man dann Unicode und UTF-XY 
beherrschen muss.

von S. R. (svenska)


Lesenswert?

Dr. Sommer schrieb:
>> Solange ich da nix rumparsen
>> muss, kann mir der Name doch egal sein.
>
> Zum Sortieren muss man das aber, wofür man
> dann Unicode und UTF-XY beherrschen muss.

Stimmt, aber das überlasse ich in der Regel auch dem Betriebssystem. :-D

von test (Gast)


Lesenswert?

Dr. Sommer schrieb:
> test schrieb:
> Und? Wofür hat man das Betriebssystem auf der Kiste?
>
> Nix Und, das ist schon gut so. Man sollte aber eben im Hinterkopf
> behalten dass da viel Komplexität drin steckt.

Ja, ist ja auch ein extrem komplexes Problem.

Genau wie Datum/Uhrzeit/Zeitpunkte. Wenn man damit zu tun hat... Das ist 
quasi ein unlösbares Problem *). Aber man kann es wenigstens versuchen, 
aber es ist halt extrem komplex.
Nur gut das alle brauchbaren Sprachen da entsprechenden Funktionen 
mitliefern (die halbwegs brauchbar sind). Da schnell mal selbst was 
zusammenzufummeln geht üblicherweise schief.


*) Wenn man einen Zeitpunkt (Datum und Uhrzeit) und einen Ort hat, dann 
braucht es eine ziemlich komplexe Datenbank um rauszufinden wie lange es 
her war. Es gibt Schaltsekunden, Länder ändern ihre Sommer-/Winterzeit 
Regeln und sie ändern ihre Zeitzonen.
Und wieviel Zeit ist zwischen dem 28.10.2018 2:30Uhr (Deutschland) und 
jetzt vergangen? ;-)

von Dr. Sommer (Gast)


Lesenswert?

test schrieb:
> Genau wie Datum/Uhrzeit/Zeitpunkte. Wenn man damit zu tun hat... Das ist
> quasi ein unlösbares Problem *). Aber man kann es wenigstens versuchen,
> aber es ist halt extrem komplex.

Oh ja... Damit hatte ich auch schon viel Spaß.

S. R. schrieb:
> Stimmt, aber das überlasse ich in der Regel auch dem Betriebssystem. :-D

Welche Betriebssysteme haben denn nativ Unicode-Sortierfunktionen? Und 
sind die dann im Kernel implementiert?

von S. R. (svenska)


Lesenswert?

Dr. Sommer schrieb:
>> Stimmt, aber das überlasse ich in der Regel auch dem Betriebssystem.
> Welche Betriebssysteme haben denn nativ Unicode-Sortierfunktionen?

Wenn ich eine Dialogbox aufmache, um den Nutzer eine Datei auswählen zu 
lassen, ist mir die Sortierung relativ egal. In der Regel kann der 
Nutzer sogar selbst aussuchen, was er gern hätte.

Textprogramme bekommen ihre Dateinamen bei mir in der Regel direkt 
übergeben. Wenn dann ein open() fehlschlägt, weder mein Problem noch ein 
katastrophales Ereignis.

Dr. Sommer schrieb:
> Und sind die dann im Kernel implementiert?

Nö, aber ziemlich sicher im verwendeten Toolkit.

von (prx) A. K. (prx)


Lesenswert?

S. R. schrieb:
> Wenn ich eine Dialogbox aufmache, um den Nutzer eine Datei auswählen zu
> lassen, ist mir die Sortierung relativ egal.

Du hast wohl noch nie eine grosse Directory gesehen.

Dir als Entwickler glaube ich das. Testszenarien bei Entwicklern sind 
eigentlich immer schön übersichtlich. Fluchen tut ja auch nicht der 
Entwickler, sondern der Anwender.

> In der Regel kann der
> Nutzer sogar selbst aussuchen, was er gern hätte.

Glücklicherweise ja. Es gibt aber leider Software, in der das nicht 
möglich ist. Das kann recht unangenehm auffallen.

: Bearbeitet durch User
von S. R. (svenska)


Lesenswert?

A. K. schrieb:
>> Wenn ich eine Dialogbox aufmache, um den Nutzer eine Datei auswählen zu
>> lassen, ist mir die Sortierung relativ egal.
> Du hast wohl noch nie eine grosse Directory gesehen.

Doch, aber in der Regel habe ich die selbst verursacht und kann damit 
einigermaßen umgehen. Notfalls mit "rm -rf". :-)

A. K. schrieb:
> Testszenarien bei Entwicklern sind eigentlich immer schön
> übersichtlich. Fluchen tut ja auch nicht der Entwickler,
> sondern der Anwender.

Ich frage mich gerade, welches Szenario du gerade im Hinterkopf hast. 
:-)

Wenn ich 10.000 Dateien in einem Ordner habe, wie soll meine Software es 
dem Benutzer denn einfacher machen, eine Datei auszusuchen? Der 
Standard-Dialog ist jedenfalls wesentlich besser getestet und sollte 
besser funktionieren als eine von mir zusammengefrickelte Alternative.

von Dr. Sommer (Gast)


Lesenswert?

S. R. schrieb:
> Der Standard-Dialog i

Wenn du den benutzt ist's ja gut. Der kann ja auch sortieren.

S. R. schrieb:
> Ich frage mich gerade, welches Szenario du gerade im Hinterkopf hast.
> :-)

Leute die alles nach "Eigene Dateien" speichern. Die finden dann Sachen 
nur nach dem "zuletzt geändert" Datum. Ok, danach zu sortieren ist 
einfach. Manche benennen auch ihre Ordner "1. Privat", "2. Arbeit", usw 
und erwarten dass die dann auch immer entsprechend sortiert sind.

von (prx) A. K. (prx)


Lesenswert?

S. R. schrieb:
>>> Wenn ich eine Dialogbox aufmache, um den Nutzer eine Datei auswählen zu
>>> lassen, ist mir die Sortierung relativ egal.
>
> Standard-Dialog ist jedenfalls wesentlich besser getestet und sollte
> besser funktionieren als eine von mir zusammengefrickelte Alternative.

Das ist ja auch meist der richtige Ansatz. Eine chronologisch statt 
namentlich sortierte Listbox mit 50 Einträgen, wie z.B. in der VMware 
Netzwerk-Auswahl, ist der falsche.

: Bearbeitet durch User
von test (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Welche Betriebssysteme haben denn nativ Unicode-Sortierfunktionen? Und
> sind die dann im Kernel implementiert?

IIRC Windows (macht Sinn, Windows selber braucht das ja auch selbst), 
aber vermutlich gehört so etwas auch bei Linux und Apple zum 
Lieferumfang.

Wobei es mir persönlich erstmal egal ist ob meine Entwicklungsumgebung 
die Betriebssystemfunktionen kapselt oder es selbst macht.

von Tom G. (masterx244)


Lesenswert?

S. R. schrieb:
> --SCHNIPP--
> Die meisten mir bekannten Sprachen verwenden allerdings utf8.
> Die JVM nutzt intern UCS16, kann also ohnehin nur die BMP (Basic
> Multilingual Plane).
> --SCHNIPP--
Surrogate-Paare. Damit kommt man auch in die anderen Bereiche rüber
===> https://de.wikipedia.org/wiki/UTF-16 Abschnitt Kodierung

von S. R. (svenska)


Lesenswert?

Tom G. schrieb:
> Surrogate-Paare.

Oh, danke für den Hinweis.
Also die Nachteile von UTF8 und UCS-2 vereint.

von Marco H. (damarco)


Lesenswert?

Dr. Sommer schrieb:

> Außer Beschimpfungen zu meinem C-Code wurde bisher kein besserer
> gezeigt. Daher gehe ich mal davon aus, dass es doch nicht signifikant
> besser geht.
1
       #define _DEFAULT_SOURCE
2
       #include <dirent.h>
3
       #include <stdio.h>
4
       #include <stdlib.h>
5
6
       int
7
       main(void)
8
       {
9
           struct dirent **namelist;
10
           int n;
11
12
           n = scandir(".", &namelist, NULL, alphasort);
13
           if (n == -1) {
14
               perror("scandir");
15
               exit(EXIT_FAILURE);
16
           }
17
18
           while (n--) {
19
               printf("%s\n", namelist[n]->d_name);
20
               free(namelist[n]);
21
           }
22
           free(namelist);
23
24
           exit(EXIT_SUCCESS);
25
       }

Mit Fnmatch sind auch ausgefallene Sortierungen möglich.. Ob das 
poartable ist weiß ich nicht..

von Marco H. (damarco)


Lesenswert?

1
static int filter_match(const struct dirent *pDirent){
2
3
  if(fnmatch(LOG_FILENAME"*", pDirent->d_name, 0) == 0 && pDirent->d_type == DT_REG)return 1;
4
5
  return 0;
6
}

hier mal ein einfacher filter welcher mit versionsort(), mir meine 
logfiles sortiert so das ich herausfinden kann welches das ältere ist um 
dies dann zu löschen ;)

Der Platzhalter "*" Filter -> test0.log test1.log usw...

: Bearbeitet durch User
von Dr. Sommer (Gast)


Lesenswert?

Ah danke, diese Möglichkeiten kannte ich noch nicht. Wüsste aber nicht, 
warum mein C Code so schlecht sein sollte nur weil er das klassische 
readdir benutzt. Der C++ Code ist übrigens Standard-C++ und damit 
portabel.

von Marco H. (damarco)


Lesenswert?

Es wird noch komplizierter ;)

scandir() hat einen blöden Nachteil..

zumindest unter Linux, wird ein doppel pointer vom type struct dirent 
erwartet.

Diese Struktur enthält nur Informationen zum namen und type.

Keine Attribute, size,Description,time etc. was aber genau so vom 
Interesse wäre wie der Name.

Also müsste man das Array mit Hilfe von qsort() und stat() erneut 
sortieren.

Ich frage mich gerade zu solchen Problemen müsste es doch Bibliotheken 
geben? Kennt jemand welche ?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marco H. schrieb:
> Keine Attribute, size,Description,time

Weil dies unter Posix-Umgebungen Eigenschaften des jeweiligen Objektes 
sind, nicht von dessen Verzeichniseintrag. Es benötigt also in jedem 
Falle ohnehin die Indirektion, aus dem Verzeichniseintrag das Objekt zu 
ermitteln, um an dessen Eigenschaften zu gelangen.

Wozu aber benötigt man beim Sortieren der Anzeige denn die 
Objektattribute?

von (prx) A. K. (prx)


Lesenswert?

Marco H. schrieb:
> Diese Struktur enthält nur Informationen zum namen und type.
> Keine Attribute, size,Description,time etc. was aber genau so vom
> Interesse wäre wie der Name.

Und das hat einen soliden Grund. Viele Filesysteme unterscheiden 
zwischen der Information in der Directory und der Information zum 
eigentlichen File (Inode). Muss der opendir-API nur die Information aus 
der Directory abliefern, geht es sehr schnell. Muss er jedoch auch die 
Information aus den Inodes mitliefern, muss für jedes einzelne File ein 
eigener Disk-Zugriff auf die Inode-Information erfolgen.

Unix/Linux-Prinzip: Keep it simple. Den stat()-Aufruf für die 
Inode-Information kann der Nutzer des APIs genauso gut selber anfügen, 
wenn er sie benötigt.

: Bearbeitet durch User
von Marco H. (damarco)


Angehängte Dateien:

Lesenswert?

Das war mir bewusst, ich wollte damit nur hinweisen das der Aufwand 
etwas steigt ;)  Aber sehr gut erklärt Danke.

Wenn funktioniert sieht das dann so aus :)

von S. R. (svenska)


Lesenswert?

Marco H. schrieb:
> Wenn funktioniert sieht das dann so aus :)

Ich würde solche Listen ja bevorzugt case-insensitiv sortieren, also 
erst alles nach Kleinbuchstaben wandeln, dann sortieren (und die 
Originale anzeigen).

"F" vor "7" vor "t" ist eher unintuitiv.

von Manfred M. (bittbeisser)


Lesenswert?

Also ich arbeite auch viel mit readdir(). Es wurde ja schon gesagt, das 
readdir() die Namen in der Reihenfolge liefert, wie das Dateisystem sie 
gespeichert hat.

Welche zusätzlichen Daten readdir() liefert oder liefern kann, hängt vom 
Betriebssystem und von Dateisystem ab. Bei Ubuntu Linux und dem 
Dateisystem ext4 kann man z.B. aus dem vollen schöpfen. Aber auch da 
bekommt man manchmal als Ergebnis DT_UNKNOWN, nämlich bei einigen 
Netzwerkfreigaben. da muss man dann trotzdem stat() bemühen.

> Ich würde solche Listen ja bevorzugt case-insensitiv sortieren,...

Das ist zumindest unter Linux nicht die beste Idee, da das Dateisystem 
da keine Unterschiede macht. Dazu kommt dann noch, das man bei der 
Sortierung evtl. noch spezielle Eigenheiten der Sprache berücksichtigen 
möchte, damit öäüß richtig einsortiert werden.

Aber möglicherweise ist scandir() eine Alternative (wenn es auf dem 
Zielsystem verfügbar ist). Da könnte man die Sortierung beeinflussen.

von S. R. (svenska)


Lesenswert?

Manfred M. schrieb:
>> Ich würde solche Listen ja bevorzugt case-insensitiv sortieren,...
> Das ist zumindest unter Linux nicht die beste Idee, da das
> Dateisystem da keine Unterschiede macht.

Das Dateisystem unterscheidet zwischen Groß- und Kleinschreibung, aber 
deswegen muss es die Sortierung in der Anzeige ja nicht tun. Schau mal 
in die Ausgabe von "ls", denn die sortiert (zumindest bei mir) ohne 
Berücksichtigung der Groß-/Kleinschreibung.

> Dazu kommt dann noch, das man bei der Sortierung evtl. noch
> spezielle Eigenheiten der Sprache berücksichtigen möchte,
> damit öäüß richtig einsortiert werden.

Das sowieso. Aber wenn man schon Unicode implementiert (hat), dann kann 
man auch gleich locale-aware sortieren. Zumal selbst gleiche Zeichen 
unterschiedlich sortiert werden (dt. "ö"=="o", sv. "ö"==letzter 
Buchstabe, dk/no. "ö"=="ø"==vorletzter Buchstabe).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

S. R. schrieb:
> Schau mal in die Ausgabe von "ls", denn die sortiert (zumindest bei mir)
> ohne Berücksichtigung der Groß-/Kleinschreibung.

Hängt stark von der locale ab.
1
$ env LC_COLLATE=C ls
2
AbCDe   Bdda    abcde   bodec   Æbedc
3
$ env LC_COLLATE=de_DE.UTF-8 ls
4
abcde   AbCDe   Æbedc  Bdda    bodec
5
$ env LC_COLLATE=da_DK.UTF-8 ls
6
abcde   AbCDe   Bdda    bodec   Æbedc

von Rolf M. (rmagnus)


Lesenswert?

Klassisch wurde die ASCIIbetische Sortierung auf UNIX-Systemen 
durchgeführt. Deshalb sind manche Filenamen wie z.B. Makefile oder 
README groß geschrieben - damit sie zuerst angezeigt werden.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Beim Makefile kommt noch dazu, dass "makefile" Vorrang vor "Makefile" 
hat, sodass man durch Kopieren auf die klein geschriebene Variante 
schnell eine eigene Modifikation durchführen kann.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.