Autor |
Beitrag |
jasocul
      
Beiträge: 6393
Erhaltene Danke: 147
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Fr 26.01.07 09:17
Ich bin zur Zeit am experimentieren und lese in C# Verzeichnisstrukturen von Datenträgern ein, um diese dann in einem TreeView darzustellen. Das das Zeit-Verhalten furchtbar ist, würde ich gerne einen Vergleich machen mit einer Win32-Anwendung. Irgendwie habe ich nicht die Zeit (Faulheit spielt da sicher auch ein Rolle), das mal eben zu basteln. Hat vielleicht jemand Lust sowas für mich zu basteln?
Falls ja, hier die Anforderungen:
- Einlesen der kompletten Verzeichnisstruktur eines auswählbaren Datenträgers
- keine Fortschrittsanzeige
- Ausgabe in einem TreeView
- Ausgabe der Verarbeitungszeit
Die Ergebnisse des Vergleichs, werde ich selbstverständlich hier wiedergeben.
Hier der wesentliche Teil meines Sources (nicht optimiert):
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117:
| Hier die Routine, die die Verzeichnisse holt private TreeNode GetSubDirectories(String Dir, TreeNode tn) { String[] sa; TreeNode[] tns;
if (Dir.Length > 0) { try { sa = Directory.GetDirectories(Dir);
if (sa.Length > 0) { for (int i = 0; i < sa.GetLength(0); i++) { sa[i] = sa[i].Remove(0, Dir.Length); }
if (tn == null) { tn = new TreeNode(Dir); }
tns = new TreeNode[sa.Length]; for (int i = 0; i < sa.Length; i++) { tns[i] = new TreeNode(sa[i]); }
for (int i = 0; i < tns.Length; i++) { tn.Nodes.Add(GetSubDirectories(Dir + tns[i].Text + "\\", tns[i])); }
return tn; } } catch { sa = null; } return tn; } else { return null; } }
private void cbbDrives_SelectionChangeCommitted(object sender, EventArgs e) { string s = ""; DriveInfo di; try { di = new DriveInfo(cbbDrives.Items[cbbDrives.SelectedIndex].ToString()); try { s = s + "Type: " + di.DriveType.ToString() + Environment.NewLine; } catch { } try { s = s + "Name: " + di.VolumeLabel + Environment.NewLine; } catch { } try { s = s + "Format: " + di.DriveFormat + Environment.NewLine; } catch { } try { s = s + "Size: " + di.TotalSize.ToString(); } catch { } tbxDriveInfo.Text = s; } catch { di = null; }
tvwDirectories.Nodes.Clear(); if (di != null) { DateTime dt;
dt = DateTime.Now; try { this.Cursor = Cursors.WaitCursor; dt = DateTime.Now;
TreeNode tn = GetSubDirectories(di.ToString(), null); tvwDirectories.Nodes.Add(tn); TimeSpan ts = DateTime.Now - dt; this.Cursor = Cursors.Default; MessageBox.Show(ts.ToString()); } catch { TimeSpan ts = DateTime.Now - dt; MessageBox.Show(ts.ToString()); this.Cursor = Cursors.Default; } } } } |
Es geht mir dabei nicht um meinen Source, sondern wirklich um einen Vergleich. Optimierungsvorschläge nehme ich aber gerne an, ist aber im Moment nicht mein primäres Ziel.
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 26.01.07 11:45
Ich würde das anders machen. Wozu alles auf einmal einlesen?
Das dauert doch nur unnötig lange. Auf die Idee wäre ich gar nicht gekommen, jedenfalls nicht an den Stellen, wo ich sowas bisher brauchte. Denn da mussten die ganzen Äste nicht gleich beim Start alle aufgeklappt werden.
Wenn das bei dir der Fall ist, dann geht es natürlich nicht anders.
Wie wärs jedenfalls so (ein Edit edtRootDirectory, ein Button btnSetRootDir und die TreeView trvDirectoryTree):
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52:
| procedure TForm55.btnSetRootDirClick(Sender: TObject); begin trvDirectoryTree.Items.Clear; trvDirectoryTree.Items.AddChild(trvDirectoryTree.Items.Add( trvDirectoryTree.Items.GetFirstNode, edtRootDirectory.Text), 'Dummy'); end;
procedure TForm55.trvDirectoryTreeExpanding(Sender: TObject; Node: TTreeNode; var AllowExpansion: Boolean); function GetAllDirs(Verzeichnis: String; var Ergebnisliste: TStringList): Boolean; var Search: TSearchRec; begin Result := False; Verzeichnis := IncludeTrailingPathDelimiter(Verzeichnis); if FindFirst(Verzeichnis + '*.*',fadirectory, Search)= 0 then begin repeat if((search.attr and fadirectory) = fadirectory) and(search.name[1] <> '.') then begin Ergebnisliste.Add(Verzeichnis + Search.Name); Result := True; end; Application.ProcessMessages; until FindNext(Search) <> 0; end; SysUtils.FindClose(search); end;
var i: Integer; Liste: TStringList; begin Liste := TStringList.Create; GetAllDirs(Node.Text, Liste); trvDirectoryTree.Items.Delete(Node.getFirstChild); for i := 0 to Liste.Count - 1 do trvDirectoryTree.Items.AddChild(trvDirectoryTree.Items.AddChild(Node, Liste[i]), 'Dummy'); Liste.Free; end; |
Klar, es muss noch statt des ganzen Pfades in jedem Node nur der letzte Teil hinein und eine Funktion, die die ganze Kette via Parent durchgeht und den Pfad liefert her...
|
|
jasocul 
      
Beiträge: 6393
Erhaltene Danke: 147
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Fr 26.01.07 11:58
jaenicke hat folgendes geschrieben: | Ich würde das anders machen. Wozu alles auf einmal einlesen?
Das dauert doch nur unnötig lange. Auf die Idee wäre ich gar nicht gekommen, jedenfalls nicht an den Stellen, wo ich sowas bisher brauchte. Denn da mussten die ganzen Äste nicht gleich beim Start alle aufgeklappt werden.
Wenn das bei dir der Fall ist, dann geht es natürlich nicht anders. |
Theoretisch hast Du Recht. Das Ziel ist bei mir allerdings, dass ich Informationen zu jedem Verzeichnis speichern will. Dafür muss ich leider alle Verzeichnisse haben. Insbesondere, wenn ich einen Abgleich machen muss, wenn neue Verzeichnisse hinzu kommen oder alte gelöscht werden. Zur Zeit befindet sich das aber noch in der Experimentierphase und da würde mir ein Vergleich mit Win32 natürlich helfen, mich zu entscheiden, ob es ein Win32- oder ein .NET-Projekt wird. Natürlich kann ich mir auch nochmal über das Konzept gedanken machen. Wenn es in Win32 keinen spürbaren Geschwindigkeitsvorteil gibt, dann werde ich das sowieso machen müssen. Aber soweit ist es noch nicht.
Danke für Deine Routine. Ich werde Sie noch auf meine Bedürfnisse anpassen (z.B. kein Application.ProcessMessages) und dann am Wochenende mit meiner Vergleichen.
|
|
ZeitGeist87
      
Beiträge: 1593
Erhaltene Danke: 20
Win95-Win10
Delphi 10 Seattle, Rad Studio 2007, Delphi 7 Prof., C++, WSH, Turbo Pascal, PHP, Delphi X2
|
Verfasst: Fr 26.01.07 12:04
Dann war/ist meins wohl überflüssig
LG
Stefan
Einloggen, um Attachments anzusehen!
_________________ Wer Provokationen, Ironie, Sarkasmus oder Zynismus herauslesen kann soll sie ignorieren um den Inhalt meiner Beiträge ungetrübt erfassen zu können.
|
|
jasocul 
      
Beiträge: 6393
Erhaltene Danke: 147
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Fr 26.01.07 12:08
Nö, wieso?
Ich werde einfach alle testen, die ich bekomme. Mal sehen, welches die beste Variante ist. Ich nehme auch .NET-Varianten (muss nicht c# sein).
Ich werde einfach meinen Rechner als Referenz-System nehmen.
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 26.01.07 16:26
jasocul hat folgendes geschrieben: | Theoretisch hast Du Recht. Das Ziel ist bei mir allerdings, dass ich Informationen zu jedem Verzeichnis speichern will. |
Alles klar, sowas hab ich mir fast schon gedacht... Ich hab das bei meiner Festplattenspeicheranalyse auch mal gebraucht, wie mir gerade einfällt, ich werd da einfach mal die Größenanalyse rausnehmen (auskommentieren meine ich, vielleicht kannst du ja auch damit was anfangen) und das posten.
Das müsste ich in C++ auch noch haben (also C++ Builder meine ich), muss ich mal suchen...
Naja, nachher, erstmal werd ich den Braten in den Ofen schieben, meine Eltern und meine Schwester scharren schon mit den Hufen... 
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Fr 26.01.07 22:09
Hallo!
Wenn Du Informationen zu jedem Verzeichnis speichern willst, ist es vielleicht ratsam, die Darstellung und die Daten ein wenig zu trennen. Ich habe das so gemacht:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87:
| private void Form1_Load(object sender, EventArgs e) { DateTime dt;
dt = DateTime.Now; try { this.Cursor = Cursors.WaitCursor; dt = DateTime.Now;
DirNode tn = null; GetSubNodes("E:\\", out tn); tvwDirectories.Nodes.Add(tn.ToTreeNode()); TimeSpan ts = DateTime.Now - dt; this.Cursor = Cursors.Default; MessageBox.Show(ts.ToString()); } catch { TimeSpan ts = DateTime.Now - dt; MessageBox.Show(ts.ToString()); this.Cursor = Cursors.Default; } }
public class DirNode { private string name; private string path;
public string Path { get { return path; } }
public string Name { get { return name; } set { name = value; } }
private List<DirNode> subNodes; public List<DirNode> SubNodes { get { return subNodes; } }
public DirNode(string Path) { subNodes = new List<DirNode>(); this.Name = Path.Substring(Path.LastIndexOf(System.IO.Path.DirectorySeparatorChar)); this.path = Path; }
public TreeNode ToTreeNode() { TreeNode result = new TreeNode(name); result.Tag = this;
foreach (DirNode d in subNodes) result.Nodes.Add(d.ToTreeNode());
return result; } }
private void GetSubNodes(string Dir, out DirNode tn) { tn = new DirNode(Dir);
try { String[] subDirs = Directory.GetDirectories(Dir); foreach (string d in subDirs) { DirNode sub = null; GetSubNodes(d, out sub); if (sub != null) tn.SubNodes.Add(sub); } } catch { } } |
Ich habe eine Klasse "DirNode" eingeführt, in der Du beliebige Informationen zu einem Verzeichnis ablegen kannst. Es wird zuerst einmal ein Baum dieser Klassen angelegt und kein Baum von TreeNodes. Die Klasse hat aber nun eine Methode, welche TreeNodes erstellt, die ihr entsprechen. Dabei wird die Tag-Eigenschaft jedes TreeNodes so gesetzt, dass Du bequem wieder auf die Daten zugreifen kannst.
Das Ganze war bei mir nicht schneller, aber auch nicht langsamer als Deine Methode, bietet aber IMHO mehr Möglichkeiten und eine bessere Trennung von GUI und Daten.
Grüße
Christian
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Zuletzt bearbeitet von Christian S. am Sa 27.01.07 00:45, insgesamt 1-mal bearbeitet
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 27.01.07 00:01
So, hier erstmal die Delphi für Win32 Version. Auch hier gibt es eine Klasse für Daten zum Ordner, die ich allerdings direkt an den jeweiligen Node angehängt habe. Die Daten sind also hier nicht getrennt.
In der Node-Klasse ist hier im Moment nur der volle Pfad gespeichert.
Einloggen, um Attachments anzusehen!
|
|
jasocul 
      
Beiträge: 6393
Erhaltene Danke: 147
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Sa 27.01.07 00:24
Hey, Danke für Eure Tipps. Ihr arbeitet ja schon vor.
Soweit war ich noch gar nicht. Ich weiß wohl, was ich will, aber über das Wie hatte ich mir im Detail teilweise noch gar keine Gedanken gemacht.
Das geplante Projekt entsprang einer spontanen Idee und da es vermutlich nicht so aufwändig geplant ist, habe ich ohne großen Plan angefangen. Da es noch nicht endgültig ist, dass ich das Projekt durchführe, möchte ich im Moment noch nicht zu viel verraten.
@Christian:
Unser anderes Projekt habe ich nicht vergessen. Ich will aber erst noch wieder meine C#-Kenntnisse wieder vertiefen. Sind leider wieder etwas verkümmert. 
|
|
|