@ Joe, dumm ist richtig! Außerdem muss ich darauf hinweisen, dass die entsprechende Funktion in Node.JS einwandfrei funktioniert ... Kopfschütteln bei Microsoft ...
NH.
2
@zwcloud Für .NET Core / Standard Path.Combine()dient hauptsächlich die Abwärtskompatibilität (mit dem vorhandenen Verhalten). Verwenden Sie besser Path.Join(): "Im Gegensatz zur Combine-Methode versucht die Join-Methode nicht, den zurückgegebenen Pfad zu rooten. (Wenn also path2 ein absoluter Pfad ist, verwirft die Join-Methode Pfad1 nicht und gibt path2 nicht als Combine zurück Methode tut.) "
Stajs
Antworten:
201
Dies ist eine Art philosophische Frage (die vielleicht nur Microsoft wirklich beantworten kann), da sie genau das tut, was in der Dokumentation steht.
Ich weiß nicht, was das Grundprinzip ist. Ich denke, die Lösung besteht darin, DirectorySeparatorChar vom Anfang des zweiten Pfades zu entfernen (oder zu trimmen). Schreiben Sie möglicherweise Ihre eigene Combine-Methode, die dies ausführt, und rufen Sie dann Path.Combine () auf.
Wenn Sie sich den zerlegten Code ansehen (siehe meinen Beitrag), haben Sie in gewisser Weise Recht.
Gulzar Nazim
7
Ich würde vermuten, dass es so funktioniert, um einen einfachen Zugriff auf den Algorithmus "Aktuelles Arbeitsverzeichnis" zu ermöglichen.
BCS
Es scheint so zu funktionieren, als würde man eine Sequenz cd (component)von der Kommandozeile aus ausführen. Klingt für mich vernünftig.
Adrian Ratnapala
11
Ich benutze diese Trimmung, um die gewünschte Effektzeichenfolge zu erhalten. StrFilePath = Path.Combine (basePath, otherPath.TrimStart (neues Zeichen [] {'\\', '/'}));
Matthew Lock
3
Ich habe meine Arbeits Code ändern in Path.Combinenur um sicher zu sein , aber dann brach es .. Es ist so dumm :)
SOTN
23
Dies ist der disassemblierte Code aus der .NET Reflector for Path.Combine-Methode. Überprüfen Sie die IsPathRooted-Funktion. Wenn der zweite Pfad gerootet ist (beginnt mit einem DirectorySeparatorChar), geben Sie den zweiten Pfad unverändert zurück.
Ich finde es auch ziemlich ärgerlich, dass dieses String-Handling manuell durchgeführt werden muss, und ich würde mich für den Grund dafür interessieren.
Meiner Meinung nach ist dies ein Fehler. Das Problem ist, dass es zwei verschiedene Arten von "absoluten" Pfaden gibt. Der Pfad "d: \ mydir \ myfile.txt" ist absolut, der Pfad "\ mydir \ myfile.txt" wird auch als "absolut" betrachtet, obwohl der Laufwerksbuchstabe fehlt. Meiner Meinung nach besteht das richtige Verhalten darin, den Laufwerksbuchstaben aus dem ersten Pfad voranzustellen, wenn der zweite Pfad mit dem Verzeichnistrennzeichen beginnt (und kein UNC-Pfad ist). Ich würde empfehlen, eine eigene Helfer-Wrapper-Funktion zu schreiben, die das gewünschte Verhalten aufweist, wenn Sie es benötigen.
Es entspricht der Spezifikation, ist aber auch nicht das, was ich erwartet hätte.
Dthrasher
@Jake Damit wird ein Bugfix nicht vermieden. Das sind mehrere Leute, die lange und gründlich darüber nachdenken, wie sie etwas tun sollen, und sich dann an das halten, worüber sie sich einig sind. Beachten Sie auch den Unterschied zwischen dem .Net-Framework (einer Bibliothek, die enthält Path.Combine) und der C # -Sprache.
Wenn einer der angegebenen Pfade eine Zeichenfolge mit der Länge Null ist, gibt diese Methode den anderen Pfad zurück. Wenn path2 einen absoluten Pfad enthält, gibt diese Methode path2 zurück.
Einige raten, dass die Namespaces kollidieren sollten, ... Ich ging mit Pathy, als geringfügig, und um eine Namespace-Kollision mit zu vermeiden System.IO.Path.
Da ich die tatsächlichen Details nicht kenne, wird davon ausgegangen, dass versucht wird, sich anzuschließen, als ob Sie relativen URIs beitreten könnten. Beispielsweise:
Dies bedeutet, dass Sie beim Verbinden eines Pfads mit einem vorhergehenden Schrägstrich tatsächlich eine Basis mit einer anderen verbinden. In diesem Fall hat die zweite Priorität.
Ich denke, die Schrägstriche sollten erklärt werden. Was hat das mit .NET zu tun?
Peter Mortensen
3
Grund:
Ihre zweite URL wird als absoluter Pfad betrachtet. Die CombineMethode gibt den letzten Pfad nur zurück, wenn der letzte Pfad ein absoluter Pfad ist.
Lösung: Entfernen Sie einfach den ersten Schrägstrich /Ihres zweiten Pfads ( /SecondPathnach SecondPath). Dann funktioniert es wie von Ihnen ausgenommen.
Dies ist in gewisser Weise sinnvoll, wenn man bedenkt, wie (relative) Pfade normalerweise behandelt werden:
stringGetFullPath(string path){string baseDir =@"C:\Users\Foo.Bar";returnPath.Combine(baseDir, path);}// Get full path for RELATIVE file pathGetFullPath("file.txt");// = C:\Users\Foo.Bar\file.txt// Get full path for ROOTED file pathGetFullPath(@"C:\Temp\file.txt");// = C:\Temp\file.txt
Die eigentliche Frage ist: Warum werden Pfade, die mit beginnen "\", als "verwurzelt" betrachtet? Das war auch für mich neu, aber unter Windows funktioniert es so :
Zuerst bewerte ich, ob Path2 mit / beginnt, und wenn es wahr ist, gebe Path2 ohne das erste Zeichen zurück. Andernfalls geben Sie den vollständigen Pfad2 zurück.
Es ist wahrscheinlich sicherer, den == @"\"Scheck durch einen zu ersetzenPath.IsRooted() Anruf , da dies "\"nicht das einzige Zeichen ist, das berücksichtigt werden muss.
rumblefx0
0
Diese beiden Methoden sollten Sie davor bewahren, versehentlich zwei Zeichenfolgen zu verbinden, in denen beide das Trennzeichen enthalten.
Dies bedeutet "das Stammverzeichnis des aktuellen Laufwerks". In Ihrem Beispiel bedeutet dies den Ordner "test" im Stammverzeichnis des aktuellen Laufwerks. Dies kann also gleich "c: \ test" sein.
Wie von Ryan erwähnt, macht es genau das, was in der Dokumentation steht.
Von den DOS-Zeiten werden die aktuelle Festplatte und der aktuelle Pfad unterschieden.
\ist der Root-Pfad, aber für die CURRENT DISK.
Für jede " Festplatte " gibt es einen separaten " aktuellen Pfad ". Wenn Sie die Festplatte mit ändern, ändern cd D:Sie nicht den aktuellen Pfad zuD:\ , sondern in: "D: \ was auch immer \ war \ der \ letzte \ Pfad \, auf den \ auf \ dieser \ Festplatte zugegriffen wurde" ...
In Windows @"\x"bedeutet ein Literal also: "CURRENTDISK: \ x". Daher Path.Combine(@"C:\x", @"\y")hat als zweiter Parameter einen Root-Pfad, keinen Verwandten, obwohl nicht auf einer bekannten Festplatte ... Und da nicht bekannt ist, welche die «aktuelle Festplatte» sein könnte, gibt Python zurück "\\y".
Path.Combine()
dient hauptsächlich die Abwärtskompatibilität (mit dem vorhandenen Verhalten). Verwenden Sie besserPath.Join()
: "Im Gegensatz zur Combine-Methode versucht die Join-Methode nicht, den zurückgegebenen Pfad zu rooten. (Wenn also path2 ein absoluter Pfad ist, verwirft die Join-Methode Pfad1 nicht und gibt path2 nicht als Combine zurück Methode tut.) "Antworten:
Dies ist eine Art philosophische Frage (die vielleicht nur Microsoft wirklich beantworten kann), da sie genau das tut, was in der Dokumentation steht.
System.IO.Path.Combine
"Wenn Pfad2 einen absoluten Pfad enthält, gibt diese Methode Pfad2 zurück."
Hier ist die eigentliche Kombinationsmethode aus der .NET-Quelle. Sie können sehen, dass CombineNoChecks aufgerufen wird , das dann IsPathRooted auf Pfad2 aufruft und diesen Pfad zurückgibt, wenn dies der Fall ist:
Ich weiß nicht, was das Grundprinzip ist. Ich denke, die Lösung besteht darin, DirectorySeparatorChar vom Anfang des zweiten Pfades zu entfernen (oder zu trimmen). Schreiben Sie möglicherweise Ihre eigene Combine-Methode, die dies ausführt, und rufen Sie dann Path.Combine () auf.
quelle
cd (component)
von der Kommandozeile aus ausführen. Klingt für mich vernünftig.Path.Combine
nur um sicher zu sein , aber dann brach es .. Es ist so dumm :)Dies ist der disassemblierte Code aus der .NET Reflector for Path.Combine-Methode. Überprüfen Sie die IsPathRooted-Funktion. Wenn der zweite Pfad gerootet ist (beginnt mit einem DirectorySeparatorChar), geben Sie den zweiten Pfad unverändert zurück.
quelle
Ich wollte dieses Problem lösen:
Natürlich sollten alle Pfade 1-9 am Ende eine äquivalente Zeichenfolge enthalten. Hier ist die PathCombine-Methode, die ich mir ausgedacht habe:
Ich finde es auch ziemlich ärgerlich, dass dieses String-Handling manuell durchgeführt werden muss, und ich würde mich für den Grund dafür interessieren.
quelle
Meiner Meinung nach ist dies ein Fehler. Das Problem ist, dass es zwei verschiedene Arten von "absoluten" Pfaden gibt. Der Pfad "d: \ mydir \ myfile.txt" ist absolut, der Pfad "\ mydir \ myfile.txt" wird auch als "absolut" betrachtet, obwohl der Laufwerksbuchstabe fehlt. Meiner Meinung nach besteht das richtige Verhalten darin, den Laufwerksbuchstaben aus dem ersten Pfad voranzustellen, wenn der zweite Pfad mit dem Verzeichnistrennzeichen beginnt (und kein UNC-Pfad ist). Ich würde empfehlen, eine eigene Helfer-Wrapper-Funktion zu schreiben, die das gewünschte Verhalten aufweist, wenn Sie es benötigen.
quelle
Path.Combine
) und der C # -Sprache.Von MSDN :
In Ihrem Beispiel ist path2 absolut.
quelle
Nach dem Rat von Christian Graus in seinem Blog "Dinge, die ich an Microsoft hasse" mit dem Titel " Path.Combine ist im Wesentlichen nutzlos. " Ist hier meine Lösung:
Einige raten, dass die Namespaces kollidieren sollten, ... Ich ging mit
Pathy
, als geringfügig, und um eine Namespace-Kollision mit zu vermeidenSystem.IO.Path
.Bearbeiten : Nullparameterprüfungen hinzugefügt
quelle
Dieser Code sollte den Trick machen:
quelle
Da ich die tatsächlichen Details nicht kenne, wird davon ausgegangen, dass versucht wird, sich anzuschließen, als ob Sie relativen URIs beitreten könnten. Beispielsweise:
Dies bedeutet, dass Sie beim Verbinden eines Pfads mit einem vorhergehenden Schrägstrich tatsächlich eine Basis mit einer anderen verbinden. In diesem Fall hat die zweite Priorität.
quelle
Grund:
Ihre zweite URL wird als absoluter Pfad betrachtet. Die
Combine
Methode gibt den letzten Pfad nur zurück, wenn der letzte Pfad ein absoluter Pfad ist.Lösung: Entfernen Sie einfach den ersten Schrägstrich
/
Ihres zweiten Pfads (/SecondPath
nachSecondPath
). Dann funktioniert es wie von Ihnen ausgenommen.quelle
Dies ist in gewisser Weise sinnvoll, wenn man bedenkt, wie (relative) Pfade normalerweise behandelt werden:
Die eigentliche Frage ist: Warum werden Pfade, die mit beginnen
"\"
, als "verwurzelt" betrachtet? Das war auch für mich neu, aber unter Windows funktioniert es so :quelle
Wenn Sie beide Pfade kombinieren möchten, ohne einen Pfad zu verlieren, können Sie Folgendes verwenden:
Oder mit Variablen:
Beide Fälle geben "C: \ test \ test" zurück.
Zuerst bewerte ich, ob Path2 mit / beginnt, und wenn es wahr ist, gebe Path2 ohne das erste Zeichen zurück. Andernfalls geben Sie den vollständigen Pfad2 zurück.
quelle
== @"\"
Scheck durch einen zu ersetzenPath.IsRooted()
Anruf , da dies"\"
nicht das einzige Zeichen ist, das berücksichtigt werden muss.Diese beiden Methoden sollten Sie davor bewahren, versehentlich zwei Zeichenfolgen zu verbinden, in denen beide das Trennzeichen enthalten.
quelle
Dies bedeutet "das Stammverzeichnis des aktuellen Laufwerks". In Ihrem Beispiel bedeutet dies den Ordner "test" im Stammverzeichnis des aktuellen Laufwerks. Dies kann also gleich "c: \ test" sein.
quelle
Entfernen Sie den Start-Schrägstrich ('\') im zweiten Parameter (Pfad2) von Path.Combine.
quelle
Ich habe die Aggregatfunktion verwendet, um die Kombination von Pfaden wie folgt zu erzwingen:
quelle
Wie von Ryan erwähnt, macht es genau das, was in der Dokumentation steht.
Von den DOS-Zeiten werden die aktuelle Festplatte und der aktuelle Pfad unterschieden.
\
ist der Root-Pfad, aber für die CURRENT DISK.Für jede " Festplatte " gibt es einen separaten " aktuellen Pfad ". Wenn Sie die Festplatte mit ändern, ändern
cd D:
Sie nicht den aktuellen Pfad zuD:\
, sondern in: "D: \ was auch immer \ war \ der \ letzte \ Pfad \, auf den \ auf \ dieser \ Festplatte zugegriffen wurde" ...In Windows
@"\x"
bedeutet ein Literal also: "CURRENTDISK: \ x". DaherPath.Combine(@"C:\x", @"\y")
hat als zweiter Parameter einen Root-Pfad, keinen Verwandten, obwohl nicht auf einer bekannten Festplatte ... Und da nicht bekannt ist, welche die «aktuelle Festplatte» sein könnte, gibt Python zurück"\\y"
.quelle