जावा में वर्तमान कार्य निर्देशिका को बदलना?


169

मैं जावा प्रोग्राम के भीतर से मौजूदा वर्किंग डायरेक्टरी को कैसे बदल सकता हूं? सब कुछ मैं इस मुद्दे के बारे में दावा करने में सक्षम हूं कि आप बस ऐसा नहीं कर सकते, लेकिन मैं विश्वास नहीं कर सकता कि वास्तव में ऐसा है।

मेरे पास कोड का एक टुकड़ा है जो उस निर्देशिका से एक हार्ड-कोडित रिश्तेदार फ़ाइल पथ का उपयोग करके एक फ़ाइल खोलता है जो सामान्य रूप से शुरू होता है, और मैं बस उस कोड को किसी अन्य जावा प्रोग्राम के भीतर से इसे शुरू किए बिना उपयोग करने में सक्षम होना चाहता हूं। एक विशेष निर्देशिका। ऐसा लगता है कि आपको बस कॉल करने में सक्षम होना चाहिए System.setProperty( "user.dir", "/path/to/dir" ), लेकिन जहां तक ​​मुझे पता चल सकता है, उस लाइन को कॉल करना चुपचाप विफल रहता है और कुछ भी नहीं करता है।

मैं समझ सकता हूं कि यदि जावा ने आपको ऐसा करने की अनुमति नहीं दी है, अगर यह इस तथ्य के लिए नहीं था कि यह आपको वर्तमान कार्यशील निर्देशिका प्राप्त करने की अनुमति देता है, और यहां तक ​​कि आपको रिश्तेदार फ़ाइल पथों का उपयोग करके फ़ाइलों को खोलने की अनुमति देता है ...।


1
जानकारी प्राप्त करना और उपयोग करना इसे बदलने से अलग है। उदाहरण के लिए विंडोज पर आप आसानी से पर्यावरण चर प्राप्त कर सकते हैं लेकिन उन्हें (सिस्टम में व्यापक तरीके से) बदलना कठिन है।
फीलोहो

1
मूल्यांकन अनुभाग में Bugs.java.com/bugdatabase/view_bug.do?bug_id=4045688 "उस समय से, अब तक कोई भी ग्राहक आगे नहीं आया है या अन्यथा पहचाना नहीं गया है ..." और 2018 के अनुसार हमारे पास लगभग 175.000 हैं। इस प्रश्न के विचार :-(
वोल्फगैंग फ़ाहल

जवाबों:


146

शुद्ध जावा में ऐसा करने का कोई विश्वसनीय तरीका नहीं है। के user.dirमाध्यम से संपत्ति सेट करना System.setProperty()या java -Duser.dir=...बाद की रचनाओं को प्रभावित करना प्रतीत होता है Files, लेकिन उदाहरण के लिए नहीं FileOutputStreams

File(String parent, String child)निर्माता अगर आप अपने फ़ाइल पथ से अलग, अपने निर्देशिका पथ का निर्माण, आसान अदला-बदली की अनुमति के कर सकते हैं।

एक विकल्प एक स्क्रिप्ट को एक अलग निर्देशिका से जावा चलाने के लिए सेट करना है, या नीचे दिए गए सुझाव के अनुसार जेएनआई मूल कोड का उपयोग करना है ।

प्रासंगिक सन बग को 2008 में "ठीक नहीं होगा" के रूप में बंद कर दिया गया था।


12
मुझे नहीं लगता कि मैंने जावा और सी # के बीच एक भी अंतर पाया है जो मुझे लगता है कि, "उन जावा लोगों को यकीन है कि वे क्या कर रहे हैं पता है"
जेक

2
यह मानना ​​मुश्किल है कि जावा में कुछ पैरामीटर नहीं है "इस निर्देशिका में शुरू ..." कम से कम ...
रॉगरडपैक

5
जावा के बचाव में (और मैं एक यूनिक्स लड़का हूं जो इस सुविधा की इच्छा रखता है) ... यह एक वीएम है जो ओएस विशेष के लिए अज्ञेय होना है। कुछ ऑपरेटिंग सिस्टम में "प्रेजेंट वर्किंग डायरेक्टरी" मुहावरा उपलब्ध नहीं है।
टोनी के।

4
जावा के लिए निष्पक्ष होने के लिए, उन्हें पहले यह करना पड़ा, सी # का लाभ कई क्षेत्रों में अपनी गलतियों से सीखने में सक्षम होने का रहा है।
रयान द लीच

3
@VolkerSeibt: आगे की जांच पर, ऐसा लगता है कि user.dir केवल कुछ वर्गों के लिए काम करता है, जिसमें मैं पहले के साथ परीक्षण किया था। new FileOutputStream("foo.txt").close();फ़ाइल को मूल कार्य निर्देशिका में बनाता है, भले ही user.dir प्रोग्राम द्वारा बदल दिया गया हो।
माइकल मायर्स

37

यदि आप ProcessBuilder के साथ अपना विरासत कार्यक्रम चलाते हैं , तो आप इसकी कार्यशील निर्देशिका को निर्दिष्ट करने में सक्षम होंगे ।


1
मार्ग मैं ले गया मार्ग है। मैं निम्नलिखित के साथ एक अलग कार्यशील निर्देशिका से एक निष्पादन योग्य चलाने में सक्षम था: फ़ाइल वर्कडायर = नई फ़ाइल ("C: \\ path \\ to \\ working \\ dir \\"); ProcessBuilder pBuilder = नया ProcessBuilder ("C: \\ path \\ to \\ working \\ dir \\ निष्पादन योग्य.exe"); pBuilder.directory (WorkingDir); प्रक्रिया p ​​= pBuilder.start ();
कैटएंडकोड

29

वहाँ है प्रणाली संपत्ति "user.dir" का उपयोग कर यह करने के लिए एक तरीका है। समझने के लिए महत्वपूर्ण हिस्सा यह है कि getAbsoluteFile () को नीचे (जैसा कि नीचे दिखाया गया है) कहा जाना चाहिए या फिर डिफ़ॉल्ट "user.dir" मान के विरुद्ध सापेक्ष पथ हल किए जाएंगे।

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");
    }
}

3
निरपेक्ष पथ महत्वपूर्ण है
HackNone

5
लेकिन यह वर्तमान कार्यशील निर्देशिका को नहीं बदलता है। का ही मूल्य है user.dir। तथ्य यह है कि निरपेक्ष मार्ग महत्वपूर्ण हो जाता है।
लोर्ने का

18

जेबीएन / जेएनआई का उपयोग करके एफडब्ल्यूडी को कॉल करने के लिए, पीडब्ल्यूडी को बदलना संभव है। JRuby लोगों के पास POSIX कॉल करने के लिए एक java लाइब्रेरी है, जिसे jna-posix कहा जाता है यहाँ maven जानकारी है

आप इसके उपयोग का एक उदाहरण यहां देख सकते हैं (क्लोजर कोड, सॉरी)। फ़ंक्शन chdirToRoot को देखें


1
लगता है कि jna-posix का आधुनिक संस्करण नहीं है। मैंने कांटा लगाया और एक जोड़ा: github.com/pbiggar/jnr-posix । मैं पुष्टि कर सकता हूं कि मैं इसके साथ PWD को बदल सकता हूं।
पॉल बिगगर

हाँ। क्षमा करें, मैंने उस फ़ाइल को हटा दिया और फ़ाइल से जुड़ा यह उत्तर भूल गया। फिक्स्ड।
एलन रोनर

आप ऐसा कर सकते हैं, लेकिन यदि आप user.dirसिस्टम प्रॉपर्टी में बदलाव नहीं करते हैं, तो File.getAbsolutePath()इसके खिलाफ समाधान करेंगे user.dir, जबकि फाइल में पाथनाम OS वर्किंग डायरेक्टरी के खिलाफ हल करता है।
मॉरी

मूल प्रश्न के संबंध में, jnr-posix का उपयोग करते हुए, मैं जावा में वर्तमान कार्य निर्देशिका को कैसे बदल सकता हूं। चदिर विधि का उपयोग करने के लिए मुझे किस वर्ग का एक उदाहरण बनाना होगा? मैं वास्तव में दिए गए क्लोजर उदाहरण को नहीं समझ पाया। अग्रिम में धन्यवाद।
सैम सेंट-पेटर्सन

12

जैसा कि आपने उल्लेख किया है कि आप JVM के CWD को नहीं बदल सकते हैं, लेकिन यदि आप Runtime.exec () का उपयोग करके एक और प्रक्रिया शुरू करने जा रहे हैं, तो आप ओवरलोड विधि का उपयोग कर सकते हैं जो आपको कार्यशील निर्देशिका को निर्दिष्ट करने देता है। यह वास्तव में आपके जावा प्रोग्राम को किसी अन्य निर्देशिका में चलाने के लिए नहीं है, लेकिन कई मामलों के लिए जब किसी को एक अन्य प्रोग्राम लॉन्च करने की आवश्यकता होती है जैसे कि पर्ल स्क्रिप्ट, उदाहरण के लिए, आप उस स्क्रिप्ट की कार्यशील निर्देशिका को निर्दिष्ट कर सकते हैं, जबकि जेवीएम की कार्यशील गति को अपरिवर्तित छोड़ दें।

Runtime.exec javadocs देखें

विशेष रूप से,

public Process exec(String[] cmdarray,String[] envp, File dir) throws IOException

जहां dirउप निर्देशिका को चलाने के लिए कार्यशील निर्देशिका है


1
यह स्वीकार किए गए उत्तर की तुलना में बेहतर उत्तर लगता है (जो "शुद्ध जावा में ऐसा करने का कोई विश्वसनीय तरीका नहीं है") से शुरू होता है।)। क्या इस उत्तर को स्वीकार किए गए उत्तर के रूप में माना जा सकता है?
जॉन

11

अगर मैं सही तरीके से समझूं, तो एक जावा प्रोग्राम वर्तमान पर्यावरण चर की एक प्रति के साथ शुरू होता है । के माध्यम से कोई भी परिवर्तन System.setProperty(String, String)प्रतिलिपि को संशोधित कर रहे हैं, न कि मूल पर्यावरण चर। ऐसा नहीं है कि यह पूरी तरह से कारण है कि सूर्य ने इस व्यवहार को क्यों चुना, लेकिन शायद यह थोड़ा प्रकाश डालता है ...


2
आप पर्यावरण चर और गुणों को मिलाते दिखते हैं। पूर्व ओएस से विरासत में मिला है जबकि बाद का उपयोग कमांड लाइन पर परिभाषित किया जा सकता है -D। लेकिन मैं मानता हूँ, जेवीएम पर पूर्वनिर्धारित गुण शुरू करते हैं जैसे user.dirओएस से कॉपी किया जाता है और बाद में उन्हें बदलने से कोई मदद नहीं मिलती है।
Maaartinus

परिवर्तन user.dirप्रभावित करता है File.getAbsolutePath()और File.getCanonicalPath(), लेकिन कार्यशील निर्देशिका के ओएस का विचार नहीं है, जो यह बताता है कि फ़ाइलों को एक्सेस करते समय फ़ाइल पथनाम कैसे हल किए जाते हैं।
मॉरी

5

कार्यशील निर्देशिका एक ऑपरेटिंग सिस्टम सुविधा है (जब प्रक्रिया शुरू होती है)। आप केवल अपनी सिस्टम प्रॉपर्टी ( -Dsomeprop=/my/path) को पास क्यों नहीं करते और अपने कोड में अपनी फाइल के माता-पिता के रूप में उपयोग करते हैं:

File f = new File ( System.getProperty("someprop"), myFilename)

क्योंकि कोड के टुकड़े में एक हार्ड कोडित फ़ाइल पथ होता है, और शायद एक हार्ड-कोडेड कंस्ट्रक्टर का उपयोग करता है जो मूल निर्देशिका से काम करने के लिए निर्दिष्ट नहीं करता है। कम से कम, स्थिति मेरे पास है :)
डेविड मैन

4

यहाँ करने के लिए होशियार / आसान बात यह है कि बस अपना कोड बदलना है ताकि यह मानकर कि यह वर्तमान कार्य निर्देशिका में मौजूद है फ़ाइल को खोलने के बजाय (मुझे लगता है कि आप कुछ ऐसा कर रहे हैं new File("blah.txt"), बस अपने आप फ़ाइल का पथ बनाएं।

उपयोगकर्ता को बेस डायरेक्टरी में पास होने दें, इसे एक कॉन्फिग फ़ाइल से पढ़ें, user.dirअगर अन्य प्रॉपर्टीज़ नहीं मिल पाती हैं, तो वापस गिर जाएं , लेकिन आपके प्रोग्राम में लॉजिक को सुधारने के लिए यह पूरी तरह से आसान है कि इसे कैसे बदलना है पर्यावरण चर काम करते हैं।


2

मैंने आह्वान करने की कोशिश की है

String oldDir = System.setProperty("user.dir", currdir.getAbsolutePath());

यह काम करने लगता है। परंतु

File myFile = new File("localpath.ext"); InputStream openit = new FileInputStream(myFile);

FileNotFoundExceptionहालांकि फेंकता है

myFile.getAbsolutePath()

सही रास्ता दिखाता है। मैंने इसे पढ़ा है । मुझे लगता है कि समस्या यह है:

  • जावा नई सेटिंग के साथ वर्तमान निर्देशिका को जानता है।
  • लेकिन फ़ाइल हैंडलिंग ऑपरेशन सिस्टम द्वारा किया जाता है। यह दुर्भाग्य से नए सेट वर्तमान निर्देशिका को नहीं जानता है।

समाधान हो सकता है:

File myFile = new File(System.getPropety("user.dir"), "localpath.ext");

यह जेवीएम द्वारा ज्ञात मौजूदा निर्देशिका के साथ एक फ़ाइल ऑब्जेक्ट को पूर्ण बनाता है। लेकिन उस कोड को एक प्रयुक्त वर्ग में मौजूद होना चाहिए, इसे पुन: उपयोग किए गए कोड को बदलने की आवश्यकता है।

~~~~ JcHartmut


"यह एक फ़ाइल ऑब्जेक्ट बनाता है" - हाँ। लेकिन यह फाइलसिस्टम में एक फाइल नहीं बनाता है। आप उसके बाद file.createNewFile () का उपयोग करना भूल गए।
गंगनुस

2

आप उपयोग कर सकते हैं

नई फ़ाइल ("रिश्तेदार / पथ")। getAbsoluteFile ()

उपरांत

System.setProperty ("user.dir", "/ some / निर्देशिका")

System.setProperty("user.dir", "C:/OtherProject");
File file = new File("data/data.csv").getAbsoluteFile();
System.out.println(file.getPath());

छपेगा

C:\OtherProject\data\data.csv

1
कृपया ध्यान दें कि यह व्यवहार जावा 11 में बदल गया है, देखें bugs.openjdk.java.net/browse/JDK-8202127 । वे उपयोग करने की सलाह नहीं देते हैंSystem.setProperty("user.dir", "/some/directory")
मार्टिन 10

0

इस प्रश्न का अन्य संभावित उत्तर उस कारण पर निर्भर हो सकता है जो आप फ़ाइल खोल रहे हैं। क्या यह एक संपत्ति फ़ाइल या एक फ़ाइल है जिसमें आपके एप्लिकेशन से संबंधित कुछ कॉन्फ़िगरेशन है?

यदि यह मामला है तो आप क्लासपथ लोडर के माध्यम से फ़ाइल को लोड करने की कोशिश कर सकते हैं, तो इस तरह से आप किसी भी फ़ाइल को लोड कर सकते हैं जो जावा के पास है।


0

यदि आप अपने आदेशों को एक शेल में चलाते हैं, तो आप "java -cp" जैसा कुछ लिख सकते हैं और अपने द्वारा अलग किए गए किसी भी निर्देशिका को जोड़ सकते हैं: "अगर java एक निर्देशिका में कुछ नहीं ढूंढता है तो यह कोशिश करेगा और उन्हें अन्य निर्देशिकाओं में ढूंढेगा," मैं क्या करता हूँ


0

आप जेएनआई या जेएनए का उपयोग करके प्रक्रिया की वास्तविक कार्यशील निर्देशिका को बदल सकते हैं।

जेएनआई के साथ, आप डायरेक्टरी को सेट करने के लिए मूल कार्यों का उपयोग कर सकते हैं। POSIX विधि है chdir()। विंडोज पर, आप उपयोग कर सकते हैं SetCurrentDirectory()

JNA के साथ, आप मूल कार्यों को जावा बाइंडरों में लपेट सकते हैं।

विंडोज के लिए:

private static interface MyKernel32 extends Library {
    public MyKernel32 INSTANCE = (MyKernel32) Native.loadLibrary("Kernel32", MyKernel32.class);

    /** BOOL SetCurrentDirectory( LPCTSTR lpPathName ); */
    int SetCurrentDirectoryW(char[] pathName);
}

POSIX सिस्टम के लिए:

private interface MyCLibrary extends Library {
    MyCLibrary INSTANCE = (MyCLibrary) Native.loadLibrary("c", MyCLibrary.class);

    /** int chdir(const char *path); */
    int chdir( String path );
}

-1

FileSystemView का उपयोग करें

private FileSystemView fileSystemView;
fileSystemView = FileSystemView.getFileSystemView();
currentDirectory = new File(".");
//listing currentDirectory
File[] filesAndDirs = fileSystemView.getFiles(currentDirectory, false);
fileList = new ArrayList<File>();
dirList = new ArrayList<File>();
for (File file : filesAndDirs) {
if (file.isDirectory())
    dirList.add(file);
else
    fileList.add(file);
}
Collections.sort(dirList);
if (!fileSystemView.isFileSystemRoot(currentDirectory))
    dirList.add(0, new File(".."));
Collections.sort(fileList);
//change
currentDirectory = fileSystemView.getParentDirectory(currentDirectory);

आयात javax.swing.filechooser.FileSystemView;
बोर्नेक

1
यह उत्तर प्रश्न से संबंधित नहीं है।
एरोन दिगुल्ला
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.