Gibt es eine herkömmliche Möglichkeit, Dateipfadzeichenfolgen zu kombinieren?

34

In einem Beispiel:

var assets = "images/"

var sounds = assets+"sounds/"

Ist es üblicher, den Schrägstrich auf die Rückseite eines Dateipfads zu setzen?

var assets = "/images"

var sounds = assets+"/sounds"

Gibt es eine andere Methode, die allgemein gebräuchlich ist?

leuchtend
quelle
Java hat die statischen Strings File.separator und File.pathSeparator, die relevant klingen. Auf diese Weise sind Sie auf allen Plattformen sicher
Evorlor
1
@Evorlor Sie müssen jedoch selten verwenden File.separator. Die APIs Fileund Pathakzeptieren sowohl /als auch "\".
Kapex
2
Könnten Sie bitte angeben, welche Sprache Sie verwenden? Es lohnt sich wahrscheinlich, das entsprechende Tag hinzuzufügen.
Christopher Creutzig
@ChristopherCreutzig Ich verwende Java - obwohl ich gefragt habe, ob es häufig verwendete Konventionen zum Kombinieren von Dateiverzeichnissen in Zeichenfolgen gibt. Anscheinend gibt es ein paar allgemein akzeptierte Regeln und es geht um gesunden Menschenverstand, aber dieser variiert ein bisschen von Sprache zu Sprache.
3.
1
In der Unix-Welt (und in URLs) werden mehrere Schrägstriche in der Mitte eines Pfades identisch mit einem einzelnen behandelt, sodass nichts Schlimmes passieren würde, wenn Sie sich auf der Seite von mehr Schrägstrichen befinden. Es ist Teil der Single Unix-Spezifikation. siehe diese Antwort - unix.stackexchange.com/a/1919/21161
yoniLavi

Antworten:

37

Nahezu jede wichtige Programmiersprache verfügt über eine Bibliothek, die die Verzeichnisseparatoren für Sie verwaltet. Sie sollten sie nutzen. Dies vereinfacht Ihren Code und beugt Fehlern vor .

Nach meiner Erfahrung ist der übliche Grund für das Kombinieren solcher Zeichenfolgen, dass sie aus verschiedenen Quellen stammen. Manchmal sind es andere Teile aus einer Konfigurationsdatei. Manchmal ist es eine Konstante, die mit einem Funktionsargument kombiniert wird. In jedem Fall müssen Sie, wenn sie aus verschiedenen Quellen stammen, verschiedene mögliche Fälle in Bezug auf die zu kombinierenden Trennzeichen an den Enden berücksichtigen:

  • Beide Enden könnten ein Trennzeichen haben: "images/"und"/sounds"
  • Nur einer hat ein Trennzeichen: "images"und "/sounds"oder "images/"und"sounds"
  • Weder hat ein Trennzeichen: "images"und"sounds"

Die Tatsache, dass jeder Teil aus einer anderen Quelle stammt, bedeutet, dass jede Quelle ihre eigenen Vorstellungen darüber hat, welche Konventionen zu befolgen sind, wenn sich jemand Gedanken darüber macht! Was auch immer Ihren Code aufruft, sollte sich darüber keine Sorgen machen müssen . Ihr Code sollte alle Fälle behandeln, da jemand gegen Ihre Konvention verstößt . Dies führt zu Zeitverschwendung bei der Untersuchung der Fehlerursache und der Behebung. Ich hatte einige unangenehme Fälle, in denen ein Mitarbeiter eine Annahme darüber machte, wie Pfade in einer Konfigurationsdatei formatiert werden sollten, was bedeutete, dass ich nach dem Code suchen und herausfinden musste, was sie erwarteten (oder den Code reparieren).

Die meisten Hauptsprachen bieten eine Methode, um dies für Sie zu tun, die bereits viele der Fälle behandelt:

Es gibt eine Einschränkung bei diesen. Einige davon scheinen davon auszugehen, dass ein führendes Verzeichnis-Trennzeichen im zweiten Argument auf einen Stammpfad verweist und dass das erste Argument daher vollständig entfernt werden sollte. Ich weiß nicht, warum dies als nützlich erachtet wird. für mich verursacht es nur probleme. Ich wollte nie zwei Pfadabschnitte kombinieren und am Ende den ersten Teil fallen lassen. Lesen Sie die Dokumentation für spezielle Fälle sorgfältig durch und schreiben Sie, falls erforderlich, einen Wrapper, der genau das tut, was Sie wollen, anstatt dessen spezielle Behandlung.

Dies hilft zusätzlich, wenn Sie verschiedene Betriebssysteme unterstützen müssen. Diese Klassen sind fast überall für die Auswahl des richtigen Trennzeichens verantwortlich. Die Bibliotheken haben normalerweise eine Möglichkeit, Pfade zu normalisieren, um sie an die Konventionen des Betriebssystems anzupassen.

Für den Fall, dass Ihre Programmiersprache nicht über eine sofort verfügbare Bibliothek verfügt, sollten Sie eine Methode schreiben, die alle diese Fälle behandelt und diese großzügig und projektübergreifend verwendet.

Dies fällt in die Kategorie "Machen Sie keine Annahmen" und "Verwenden Sie Tools, die Ihnen helfen".

jpmc26
quelle
2
Path.Combine von .NET ist nicht fehlerhaft. Füttere es nur nicht mit Trennzeichen. Stellen Sie sicher, dass Sie die Dokumentation lesen. Wenn das zweite Argument ein Stammpfad ist, hat es ein definiertes Ergebnis. Sie mögen es vielleicht nicht, aber das heißt nicht, dass es kaputt ist.
Erno
4
Stellen Sie sicher, dass Sie die Dokumentation lesen, um sicherzustellen, dass nicht versucht wird, zu schlau zu sein. Ich habe einmal eine Bibliothek verwendet, die erfolgreich C:\Documents and Settings\Adminmit my folder:document.txteinem * nix-System kombiniert werden konnte /home/admin/my folder/document.txt- ein netter Trick, aber in der realen Welt haben die beteiligten Heuristiken mehr Fehler verursacht, als sie behoben haben.
Mark
1
Paths.get()Konvertiert für Java auch nur ein einzelnes Objekt Stringin ein PathObjekt. Um Pfade zu verbinden, verwenden Sie Path.resolve(), die ein anderes Pathoder ein anderes aufnehmen können String. Es gibt andere Methoden in der PathKlasse, mit denen Pfade auf verschiedene Arten verbunden werden können.
Kat
1
Es sieht so aus, als hätte ich die Dokumente nicht gut gelesen Paths.
Kat
1
Auf Powershell, eine Alternative zu dem .NET - Methode , [System.IO.Path]::Combine("abc", "\def")die das beschriebene Verhalten hat, ist die Cmdlets , Join-Path "abc" "\def"die gibt "abc\def".
Jeppe Stig Nielsen
38

In Java wäre die Antwort "keines der oben genannten". Es wird empfohlen, Pfadnamen mithilfe der java.io.FileKlasse zusammenzustellen. z.B

File assets = new File("images");
File sounds = new File(assets, "sounds");

Die FileKlasse kümmert sich auch um plattformspezifische Pfadnamentrennzeichen.

Es gibt eine separate Frage, ob Ihr Pfadname mit einem Schrägstrich beginnen soll oder nicht. Das hat aber mehr mit Korrektheit als mit Best Practice zu tun. Ein Pfadname, der mit einem Schrägstrich beginnt, bedeutet etwas anderes als ein Pfadname, der nicht mit einem Schrägstrich beginnt.


Es gibt keine explizite Unterstützung für die Behandlung von Pfadnamen in der ECMA-Javascript-Bibliothek, aber (zumindest) Node.js bietet Unterstützung über das Path-Modul.

Stephen C
quelle
4
Ähnliches gilt auch für die .Net Framework-Sprachen und alle anderen, die Dateisystemklassen anbieten.
James Snell
3
Vielen Dank! Dies schien die hilfreichste Antwort zu sein, obwohl es sprachspezifische Bibliotheken für andere Sprachen im Allgemeinen wie .NET und C ++ geben sollte.
2.
3
Tatsächlich sollte jeder Code, der keine Bibliothek verwendet, bei der Codeüberprüfung abgelehnt werden. In dem seltenen Fall, dass keine Bibliothek vorhanden ist, besteht die Antwort darin, eine selbst zu schreiben, anstatt rohe Zeichenfolgen einzufügen.
Gort the Robot
C ++ hat Boost :: Filesystem und C # hat System.IO.Path
Mooing Duck
Python hat os.path.join. PowerShell hat join-path. Ich würde dieser Antwort etwas hinzufügen. Ich habe festgestellt, dass, wenn Sie Dateipfade in mehreren Teilen benötigen, Ihr Code sehr zerbrechlich wird, wenn Sie Annahmen über Dateipfade an bestimmten Stellen treffen. Die Verwendung dieser Klassen trägt nicht nur zur Portabilität bei, sondern behandelt auch alle möglichen Kantenfälle (Schrägstrich an beiden zu verbindenden Enden, Schrägstrich nur auf einer Seite, überhaupt kein Schrägstrich dazwischen). Diese Flexibilität ist von unschätzbarem Wert, wenn Sie Dateipfade in einer Konfigurationsdatei ablegen.
jpmc26
21

Beachten Sie, dass Sie in .NET die Path.Combine-Methode verwenden sollten.

var path = System.IO.Path.Combine("assets", "sounds");

Der Grund dafür ist, dass es die richtigen Zeichen "kennt" , die beim Erstellen der Ordnernamen verwendet werden.

Dies beseitigt das "Problem" der Vor- oder Nachfixierung.

Erno
quelle
4
os.path.join macht im Grunde dasselbe auch für Python
StarWeaver
Beachten Sie, dass path.combine Sie nicht davon abhält, sich Sorgen um den Trenner zu machen: stackoverflow.com/questions/53102/…
jmoreno
1
@jmoreno - In meinem Beispiel gibt es KEINE Trennzeichen. Die Frage, mit der Sie verknüpft haben, hat fest codierte Trennzeichen und ist grundsätzlich falsch, da der zweite Pfad ein absoluter Pfad ist.
Erno
Aber sei vorsichtig damit. Bei .NET bin ich mir nicht sicher, aber es os.path.join('src', '../../../your_secret_stuff') ist in Python gültig. Verwenden Sie diese Methoden also nicht blind für Benutzereingaben.
Sapi
@sapi - Natürlich sollten Benutzereingaben immer bereinigt werden, aber das liegt in der Verantwortung des Programmierers und nicht der API.
Erno
5

Beim Erstellen von Pfaden verwende ich oft eine Funktion, die den abschließenden Schrägstrich hinzufügt, wenn er nicht bereits vorhanden ist. Dann können Pfade wie folgt aufgebaut werden:

filename := fs( 'assets') + fs( 'images') + fs( 'icons') + 'some.png';

Dabei fügt fs () bei Bedarf einen abschließenden Schrägstrich hinzu.

GroßmeisterB
quelle
5

Ordner und Dateien unterscheiden sich nur in einem Aspekt: ​​Ordner enden mit einem Schrägstrich, Dateien nicht. Darüber hinaus beginnen absolute Pfade mit einem Punkt, an /dem relative Pfade nicht vorkommen. Wenn Sie dies verwenden, sollte es kein Problem sein, Pfade und Dateien konsistent miteinander zu verknüpfen.

var absolutepath = "/my/path/";
var relativepath = "css/";
var filename = "test.css";
var relativepathtofilename = "js/test.js";

var a = absolutepath + relativepath + filename; //Output: /my/path/css/test.css
var b = absolutepath + relativepathtofilename;  //Output: /my/path/js/test.js

Die Verknüpfung zweier absoluter Pfade macht keinen Sinn, da der zweite Pfad relativ zum ersten Pfad sein sollte. Die Verknüpfung zweier relativer Pfade ist kein Problem, kann jedoch zu undefiniertem Verhalten führen, wenn das Programm nicht weiß, wo sich der relative Pfad befindet.

Sumurai8
quelle
Dies hat meine ursprüngliche Frage wahrscheinlich am besten beantwortet. Ich denke, ich verstehe Dateipfade besser, obwohl, wie Stephen C und Erno sagten, Sprachbibliotheken die beste erste Wahl sind. Dies erklärt die Konvention jedoch besser. Vielen Dank!
2.
Dateisystempfade oder URLs?
MrWhite
1
In jeder Hinsicht können Sie dies auch auf uri's anwenden. Ein absoluter Uri würde mit einem Protokoll beginnen, aber ansonsten wäre dies meiner Meinung nach dasselbe.
Sumurai,
Nicht sicher, wie Ihre Ausgabe funktioniert. Wenn ich es tue, bekomme ich:var a = "/my/path" + "css/" + "test.css"; //Output: "/my/pathcss/test.css"
Damon
1
@Damon Ich habe einen Schnitt gemacht. absolutepathhätte mit einem Schrägstrich enden sollen, weil es ein Pfad ist. Irgendwie habe ich das übersehen, als ich das geschrieben habe.
Sumurai8
4

Ich denke, es gibt keine Magie oder "gängige Praxis" für die Implementierung von Pfaden, aber die Verkettung von Zeichenfolgen ist sicherlich nicht der richtige Weg. Sie können Ihre eigene API für die Bearbeitung von Fällen entwickeln, dies kann jedoch einige Anstrengungen erfordern. Insbesondere sollten Sie mit unterschiedlichen Plattformen vorsichtig sein. Beispielsweise ist in Windows \das Trennzeichen, während in Unix-basierten Systemen /das Trennzeichen ist.

Ich bin nicht mit Javascript-Bibliotheken vertraut, aber ich bin mir sicher, dass es Bibliotheken für die Behandlung dieser Fälle geben sollte. In Java können Sie beispielsweise die Pfad- API verwenden, um plattformunabhängige Pfadvorgänge zu verarbeiten.

Wickoo
quelle
3
Windows unterstützt tatsächlich /als Pfaddateibegrenzer. Dies erfordert Macken in der Befehlszeile, aber Datei-E / A-APIs funktionieren gut mit Schrägstrichen.
Ruslan
en.wikipedia.org/wiki/… "Die Windows-System-API akzeptiert Schrägstriche, und daher sollten alle oben genannten Unix-Beispiele funktionieren. Viele Anwendungen unter Windows interpretieren Schrägstriche jedoch für andere Zwecke oder behandeln sie als ungültige Zeichen und erfordern Sie daher Eingabe von Backslash - insbesondere der cmd.exe-Shell (häufig als "Terminal" bezeichnet, da sie normalerweise in einem Terminalfenster ausgeführt wird). "
Mooing Duck
0

Meine persönliche Präferenz ist folgende:

var assets = "/images"

var sounds = assets+"/sounds"

Ich benutze immer absolute Pfade ( /images/...), es fühlt sich für mich weniger fehleranfällig an. Es ist auch einfacher zu verwenden, var sounds = assets+"/sounds"denn selbst wenn Sie assetseinen abschließenden Schrägstrich hätten und am Ende einen hätten /images//sounds, würde er sich dennoch auflösen /images/sounds. Der einzige Haftungsausschluss ist, dass er von Ihrem Anforderungsbearbeiter abhängt. Apache scheint das in Ordnung zu bringen (zumindest bestimmte Versionen / Konfigurationen, siehe http://www.amazon.com//gp//site-directory//ref=nav_sad ). Auf die andere Art und Weise, die Ihnen /imagessoundsnichts ausmacht :) Es besteht auch die Möglichkeit, nach doppelten Schrägstrichen zu suchen und diese zu bereinigen. Keine Option mit dem anderen Ansatz.

rpaskett
quelle
11
In allen mir bekannten Zusammenhängen ist ein Pfad, der mit einem Schrägstrich ( /) beginnt, ein absoluter Pfad, kein relativer Pfad. Oder meintest du es nur für andere Streckenabschnitte als den ersten?
Bart van Ingen Schenau
@BartvanIngenSchenau Ich stimme Ihnen voll und ganz zu und nenne sie das seit Jahren, aber jedes Mal, wenn ich einen Artikel eines Front-End-Entwicklers lese, bezeichnen sie sie als relative Pfade. Ich wollte keine Annahmen treffen, also habe ich wohl das kleinere von zwei Übeln ausgewählt ...? Jetzt, da ich weiß, dass ich ein paar Leute auf meiner Seite habe, aktualisiere ich meine Antwort :)
rpaskett
2
Für Webentwickler /somewhereist dies ein relativer Pfad, da er den Host nicht enthält, sodass der Browser ihn basierend auf dem Host der aktuellen Seite nachschlägt. In der Webwelt http://here/somewhereist er ein absoluter URI und /somewhereelserelativ zu diesem. In der Dateisystemwelt /somewhereist es absolut und kommt von root /. "Somewhereelse" ist relativ zum aktuellen Arbeitsverzeichnis.
Rob
3
@RobY, rpaskett: RFC3986 (der RFC, der URIs definiert) http://here/somewhereist ein URI mit einem absoluten Pfad, /somewhereeine relative Referenz mit einem absoluten Pfad und somewhere/elseeine relative Referenz mit einem relativen Pfad. Offensichtlich wird in diesen Kreisen "relativer Pfad" verwendet, um sich auf eine relative Referenz zu beziehen.
Bart van Ingen Schenau
1
@BartvanIngenSchenau: In Windows ist ein Pfad, der mit einem Schrägstrich beginnt, ein relativer Pfad und relativ zu CWD. en.wikipedia.org/wiki/…
Mooing Duck
0

In Smalltalk ist es einfach, die / -Methode in String so zu definieren, dass sie folgendermaßen funktioniert:

'assets' / 'sounds' => 'assets/sounds'.
'assets/' / 'sounds' => 'assets/sounds'.
'assets' / '/sounds' => 'assets/sounds'.
'assets/' / '/sounds' => 'assets/sounds'.

Hier ist eine einfache Implementierung der Methode (Sie können sie verbessern):

/ aString
    | slash first second |
    slash := Directory separator.
    first := self.
    (first endsWith: slash) ifTrue: [first := first allButLast].
    second := aString.
    (second beginsWith: slash) ifTrue: [second := second allButFirst].
    ^first , slash , second

Hinweis : Sie können auch eine bessere Aufmerksamkeit auf Grenzfälle wie zahlen wollen '' / '', 'x/' / ''etc., um das richtige Verhalten zu bestimmen.

Leandro Caniglia
quelle