Comment modifier le répertoire de travail actuel depuis un programme Java? Tout ce que j'ai pu trouver sur le sujet affirme que vous ne pouvez tout simplement pas le faire, mais je ne peux pas croire que ce soit vraiment le cas.
J'ai un morceau de code qui ouvre un fichier en utilisant un chemin de fichier relatif codé en dur à partir du répertoire dans lequel il est normalement démarré, et je veux juste pouvoir utiliser ce code depuis un autre programme Java sans avoir à le démarrer à partir d'un répertoire particulier. Il semble que vous devriez juste pouvoir appeler System.setProperty( "user.dir", "/path/to/dir" )
, mais autant que je sache, appeler cette ligne en silence échoue et ne fait rien.
Je comprendrais si Java ne vous permettait pas de le faire, si ce n’était le fait que cela vous permet d’obtenir le répertoire de travail en cours, et vous permet même d’ouvrir des fichiers en utilisant des chemins de fichiers relatifs ....
Il n’existe aucun moyen fiable de le faire en Java pur. La définition de la propriété user.dir
via System.setProperty()
ou Java -Duser.dir=...
semble affecter les créations ultérieures de Files
, mais pas p. Ex. FileOutputStreams
.
Le constructeur File(String parent, String child)
peut vous aider si vous construisez votre chemin de répertoire séparément de votre chemin de fichier, permettant ainsi un échange plus simple.
Une alternative consiste à configurer un script pour exécuter Java à partir d'un répertoire différent ou utiliser le code JNI natif comme suggéré ci-dessous .
Le bogue Sun correspondant a été fermé en 2008 sous le nom "ne résoudra pas".
Si vous exécutez votre programme existant avec ProcessBuilder , vous pourrez spécifier son fonctionnement répertoire .
Il y a = un moyen de le faire en utilisant la propriété système "user.dir". La partie clé à comprendre est que getAbsoluteFile () doit être appelé (comme indiqué ci-dessous), sinon les chemins relatifs seront résolus par rapport à default "user.dir " valeur.
import Java.io.*;
public class FileUtils
{
public static boolean setCurrentDirectory(String directory_name)
{
boolean result = false; // Boolean indicating whether directory was set
File directory; // Desired current working directory
directory = new File(directory_name).getAbsoluteFile();
if (directory.exists() || directory.mkdirs())
{
result = (System.setProperty("user.dir", directory.getAbsolutePath()) != null);
}
return result;
}
public static PrintWriter openOutputFile(String file_name)
{
PrintWriter output = null; // File to open for writing
try
{
output = new PrintWriter(new File(file_name).getAbsoluteFile());
}
catch (Exception exception) {}
return output;
}
public static void main(String[] args) throws Exception
{
FileUtils.openOutputFile("DefaultDirectoryFile.txt");
FileUtils.setCurrentDirectory("NewCurrentDirectory");
FileUtils.openOutputFile("CurrentDirectoryFile.txt");
}
}
Il est possible de changer le PWD en utilisant JNA/JNI pour passer des appels vers libc. Les gars de JRuby ont une bibliothèque pratique Java pour passer des appels POSIX appelés jna-posix Voici les infos maven
Vous pouvez voir un exemple de son utilisation ici (code Clojure, désolé). Regardez la fonction chdirToRoot
Si je comprends bien, un programme Java commence par un copie des variables d'environnement actuelles. Toute modification via System.setProperty(String, String)
modifie la copie, pas les variables d’environnement d’origine. Non pas que cela fournisse une raison complète pour laquelle Sun a choisi ce comportement, mais peut-être éclaircit-il un peu ...
Comme indiqué, vous ne pouvez pas modifier le CWD de la machine virtuelle, mais si vous deviez lancer un autre processus à l'aide de Runtime.exec (), vous pouvez utiliser la méthode surchargée qui vous permet de spécifier le répertoire de travail. Ce n'est pas vraiment pour exécuter votre programme Java dans un autre répertoire, mais dans de nombreux cas, lorsque vous devez lancer un autre programme comme un script Perl par exemple, vous pouvez spécifier le répertoire de travail de ce script tout en laissant le répertoire de travail. de la JVM inchangée.
Voir Runtime.exec javadocs
Plus précisément,
public Process exec(String[] cmdarray,String[] envp, File dir) throws IOException
où dir
est le répertoire de travail dans lequel exécuter le sous-processus
Le répertoire de travail est une fonction du système d'exploitation (définie au démarrage du processus). Pourquoi ne passez-vous pas votre propre propriété système (-Dsomeprop=/my/path
) et ne l'utilisez pas dans votre code en tant que parent de votre fichier:
File f = new File ( System.getProperty("someprop"), myFilename)
La chose la plus intelligente/facile à faire ici est simplement de changer votre code afin qu'au lieu d’ouvrir le fichier en supposant qu’il existe dans le répertoire de travail en cours (je suppose que vous faites quelque chose comme new File("blah.txt")
, déposer vous-même.
Laissez l'utilisateur passer dans le répertoire de base, le lire dans un fichier de configuration, revenir à user.dir
si les autres propriétés ne peuvent pas être trouvées, etc. Mais il est beaucoup plus facile d'améliorer la logique de votre programme que c'est changer le fonctionnement des variables d'environnement.
J'ai essayé d'invoquer
String oldDir = System.setProperty("user.dir", currdir.getAbsolutePath());
Cela semble fonctionner. Mais
File myFile = new File("localpath.ext"); InputStream openit = new FileInputStream(myFile);
jette un FileNotFoundException
bien que
myFile.getAbsolutePath()
montre le chemin correct. J'ai lisez ceci . Je pense que le problème est:
La solution peut être:
File myFile = new File(System.getPropety("user.dir"), "localpath.ext");
Il crée un objet Object en tant qu’objet absolu avec le répertoire en cours connu de la machine virtuelle Java. Mais ce code doit exister dans une classe utilisée, il faut changer les codes réutilisés.
~~~~ JcHartmut
Vous pouvez utiliser
nouveau fichier ("relatif/chemin"). getAbsoluteFile ()
après
System.setProperty ("user.dir", "/ some/directory")
System.setProperty("user.dir", "C:/OtherProject");
File file = new File("data/data.csv").getAbsoluteFile();
System.out.println(file.getPath());
Va imprimer
C:\OtherProject\data\data.csv
Si vous exécutez vos commandes dans un shell, vous pouvez écrire quelque chose comme "Java -cp" et ajouter tous les répertoires souhaités, séparés par ":" si Java ne trouve pas quelque chose dans un répertoire, il va essayer de les trouver. dans les autres répertoires, c'est ce que je fais.
L'autre réponse possible à cette question peut dépendre de la raison pour laquelle vous ouvrez le fichier. S'agit-il d'un fichier de propriétés ou d'un fichier contenant une configuration liée à votre application?
Si tel est le cas, vous pouvez envisager de charger le fichier par le biais du chargeur de chemin de classe. Vous pouvez ainsi charger n'importe quel fichier auquel Java a accès.