2017-03-04 28 views
6

Original post jeden że większość ludzi odpowiadaliJak odzyskać katalog roboczy uruchomionego procesu w Javie?

Oto kod Próbowałem już robi to z

String workingDirectory = "/home"; 
String command = "cd ../"; 

ProcessBuilder pb = new ProcessBuilder(new String[] { "cmd", "/c", command }); 
pb.directory(new File(workingDirectory)); 
pb.redirectErrorStream(true); 
Process process = pb.start(); 

// Some time later once the process has been closed 
workingDirectory = pb.directory().getAbsolutePath(); 
System.out.println("Path: " + workingDirectory); 

ten nie działa, po jej zakończeniu to wychodzi z ten sam katalog roboczy .

Każda pomoc zostanie bardzo doceniona, będzie to bardzo przydatne.

Dokładniej, szukam katalogu roboczego dynamicznie tworzonego procesu w Javie, na przykład w powyższym fragmencie. Jest to ważne, ponieważ takie jak predefiniowane polecenie powyżej, katalogi robocze mogą się czasami zmieniać, chciałbym zapisać zmiany w pamięci do późniejszego wykorzystania.

znalazłem sposób, aby to zrobić, i wydaje się działać bez problemów

Oto jak ja obsługę przychodzących katalog roboczy

public int osType = 1; // This is for Windows (0 is for Linux) 

public boolean isValidPath(String path) { 
    try { 
     Paths.get(new File(path).getAbsolutePath()); 
    } catch (InvalidPathException | NullPointerException ex) { 
     return false; 
    } 
    return true; 
} 

public String tracePath(String path) { 
    try { 
     if (!path.contains("%%") && !isValidPath(path)) return null; 
     if (path.contains("%%")) path = path.substring(path.indexOf("%%")); 
     int lastIndex = -1; 
     char filesystemSlash = ' '; 
     if (osType == 0) 
      filesystemSlash = '/'; 
     if (osType == 1) 
      filesystemSlash = '\\'; 
     if (osType == 0) 
      path = path.substring(path.indexOf(filesystemSlash)); 
     if (osType == 1) 
      path = path.substring(path.indexOf(filesystemSlash) - 2); 
     String tmp = path; 
     boolean broken = true; 
     while (!isValidPath(tmp)) { 
      int index = tmp.lastIndexOf(filesystemSlash); 
      if (lastIndex == index) { 
       broken = false; 
       break; 
      } 
      tmp = tmp.substring(0, index); 
      lastIndex = index; 
     } 
     if (broken && lastIndex != -1) { 
      tmp = path.substring(0, lastIndex); 
     } 
     return tmp; 
    } catch (StringIndexOutOfBoundsException ex) { 
     return null; 
    } 
} 

Oto metoda ignorowania problemy ze ścieżką (przez jej nieużywanie)

public boolean setDirectory(ProcessBuilder pb, String path) { 
    try { 
     pb.directory(new File(new File(path).getAbsolutePath())); 
     return true; 
    } catch (Exception ex) { 
     return false; 
    } 
} 

Oto jak ja rozpoczęciem procesu dla systemu Windows lub Linux

File file = null; 
     if (osType == 1) { 
      ProcessBuilder pb = new ProcessBuilder(new String[] { "cmd", "/c", command + " & echo %% & cd" }); 
      pb.redirectErrorStream(true); 
      if (!workingDirectory.equals("")) 
       setDirectory(pb, workingDirectory); 
      process = pb.start(); 
     } else if (osType == 0) { 
      file = new File("script.sh"); 
      FileWriter writer = new FileWriter(file, false); 
      writer.append(command + " && echo %% && pwd"); 
      writer.flush(); 
      writer.close(); 
      ProcessBuilder pb = new ProcessBuilder(new String[] { "bash", System.getProperty("user.dir") + "/script.sh" }); 
      pb.redirectErrorStream(true); 
      if (!workingDirectory.equals("")) 
       setDirectory(pb, workingDirectory); 
      process = pb.start(); 
     } else 
      return; 

Wreszcie tutaj jest pętla, która zarządza procesem i katalog roboczy

while (process.isAlive() || process.getInputStream().available() > 0) { 
      byte[] returnBytes = new byte[1024]; 
      process.getInputStream().read(returnBytes); 
      char[] arr = new String(returnBytes).trim().toCharArray(); 
      StringBuilder sb = new StringBuilder(); 
      for (int i = 0; i < arr.length; i++) { 
       char c = arr[i]; 
       if (Character.isDefined(c)) 
        sb.append(c); 
      } 
      String response = sb.toString(); 
      if (!response.equals("")) { 
       String path = tracePath(response.trim().replace("\n", "").replace("\r", "")); 
       if (path != null && osType == 1) { 
        if (Paths.get(path).toFile().exists()) 
         workingDirectory = path; 
       } else if (path != null && osType == 0) { 
        if (Paths.get(path).toFile().exists()) 
         workingDirectory = path; 
       } 
       client.sendMessage(response + '\r' + '\n'); 
      } 
     } 
if (file != null) file.delete(); 

Tutaj jest wyjście z poleceniem odbioru strona

Connecting.. 
Connected. 
Success. You have been connected -> Speentie 

bash -c pwd 
/root/hardsceneServer/remoteServer 

%% 
/root/hardsceneServer/remoteServer 

bash -c cd .. 

%% 
/root/hardsceneServer 

bash -c pwd 
/root/hardsceneServer 

%% 
/root/hardsceneServer 

bash -c dir 
ircServer nohup.out remoteServer start.sh start1.sh start2.sh 

%% 
/root/hardsceneServer 

bash -c cd ircServer 

%% 
/root/hardsceneServer/ircServer 

bash -c dir 
HardScene.jar   hardscene_banned.properties start.sh 
hardscene.properties nohup.out 

%% 
/root/hardsceneServer/ircServer 
+0

jaka jest komenda tutaj? –

+0

Jeśli pytasz, jak odzyskać katalog roboczy innego procesu, to nie jest to możliwe. – Andreas

+0

Jak to nie jest możliwe, gdy Linux może to zrobić? Myślałem, że Java może również łączyć się z urządzeniem? Musi istnieć sposób, nawet jeśli jest niezwykle skomplikowany. – Speentie8081

Odpowiedz

4

Szukasz czegoś takiego?

System.out.println("Current working directory: " + System.getProperty("user.dir")); 
System.out.println("Changing working directory..."); 
// changing the current working directory 
System.setProperty("user.dir", System.getProperty("user.dir") + "/test/"); 

// print the new working directory path 
System.out.println("Current working directory: " + System.getProperty("user.dir")); 

// create a new file in the current working directory 
File file = new File(System.getProperty("user.dir"), "test.txt"); 

if (file.createNewFile()) { 
    System.out.println("File is created at " + file.getCanonicalPath()); 
} else { 
    System.out.println("File already exists."); 
} 

To Wyjścia:

Current working directory: /Users/Wasi/NetBeansProjects/TestProject 
Changing working directory... 
Current working directory: /Users/Wasi/NetBeansProjects/TestProject/test/ 
File is created at /Users/Wasi/NetBeansProjects/TestProject/test/test.txt 
+0

Naprawdę, prawie go masz, widzisz, kiedy ludzie wykonują coś "cd ../" w oknie poleceń, robi to dla tego jednego polecenia, ale nie zapisuje tego nowego katalogu w pamięci w Javie, ponieważ oczywiście który jest przechowywany w całkowicie nowym procesie. Potrzebuję tylko pewnego sposobu przekazania procesu i uzyskania katalogu roboczego tego procesu, aby mógł być ponownie użyty później. – Speentie8081

+0

@SkorrloreGaming Mam cię. ale dlaczego nie używasz 'System.getProperty (" user.dir ")'? Czy chcesz zapisać bieżący katalog roboczy tylko dla procesu? –

+0

Chcę konkretnie katalogu roboczego procesu dynamicznego nic innego. – Speentie8081

2

szukam znaleźć katalog roboczy dynamicznie utworzonego procesu w Javie,

Można oczywiście odnośnika katalogu roboczego bieżący proces Java, patrząc na wartość właściwości systemu user.dir:

String cwd = System.getProperty("user.dir"); 

Ale znalezienie katalogu roboczego innego procesu nie jest możliwe, chyba że używasz specjalnych wywołań systemu operacyjnego. W systemie Linux, jeśli znasz pid, możesz spojrzeć na /proc/[pid]/cwd, ale nie ma łatwego odpowiednika w systemach operacyjnych OSX lub Windows, o których wiem.

To nie działa, po zakończeniu wychodzi z tym samym katalogiem roboczym.

Tak, nie można wydać polecenia zmiany katalogu roboczego, ponieważ po wyjściu polecenia cmd katalog roboczy zostanie zresetowany.

Według this page, można ustawić katalog roboczy przypisując właściwość systemu user.dir:

System.setProperty("user.dir", "/tmp"); 

Jednak może to być zależne od systemu operacyjnego i nie działa na moim komputerze OSX. Na przykład poniższy kod tworzy x1 i x2 plików w tym samym katalogu:

new File("x1").createNewFile(); 
// this doesn't seem to do anything 
System.setProperty("user.dir", "/tmp"); 
new File("x2").createNewFile(); 

This answer mówi, że nie ma niezawodny sposób to zrobić w Javie. Zawsze uważałem, że nie można zmienić katalogu roboczego i że powinieneś być konkretny z new File(parent, filename), aby pokazać, gdzie są pliki na żywo, itp.

0

Co możesz zrobić, to użyć uchwytu od sysinternals dla okien

https://technet.microsoft.com/en-us/sysinternals/bb896655.aspx

lub

ls -l/Proc/[PID]/fd i PFiles [PID] dla Linux

i znaleźć folder ostatnio wykorzystywana przez ten proces.

String commandToGetOpenFiles="handle... or ls..."; 
BufferedReader reader = new BufferedReader(
     new InputStreamReader(Runtime.getRuntime() 
       .exec(commandToGetOpenFiles).getInputStream())); 

i zacząć przetwarzać i uzyskać PID użyć wmic wywołanie procesu tworzenia „cmd”

0

Użyj tego, aby uzyskać adres URL bieżącego katalogu plik:

URL url = ClassLoader.getSystemResource(FileName); 

Działa wszędzie . Nie tylko Twój komputer, nawet w chmurze.

Zwraca typ URL (java.net). Dla ClassLoader, nie musisz importować niczego.

W Nazwa pliku użyj nazwy pliku, do którego chcesz uzyskać ścieżkę.

-1

użyć kodu poniżej

Path currentRelativePath = Paths.get(""); 
String s = currentRelativePath.toAbsolutePath().toString(); 
System.out.println("Current relative path is: " + s); 
2

To nie może być osiągnięty w Javie przez ProcessBuilder „s directory() metody, ponieważ ustawia katalog roboczy procesu, w którym nie jest binarny. Musisz to zrobić na innym poziomie.

Jeśli pracujesz z GNU/Linux, najlepszym wyborem są whereis i update-alternative. W systemie Windows masz where. Teraz przychodzi do użycia poleceń w różnych systemach operacyjnych i parsowania wyników. To może być trudne.

Niektóre pseudokod zacząć:

  1. wykonać whereis plus jako parametr polecenia, z ProcessBuilder
  2. starają się analizować dane wyjściowe. Możesz zajmować się wieloma liniami wyjściowymi.

Albo

  1. wykonać update-alternatives plus jako parametr polecenia, z ProcessBuilder
  2. starają się analizować dane wyjściowe. Może być kilka alternatyw dla jednego polecenia, na przykład dla java, możesz mieć zainstalowane różne JDK.
  3. Lub listę wszystkich linków w /var/libs/alternatives i znaleźć to, co chcesz, może z rur. Można zobaczyć tutaj:

https://serverfault.com/questions/484896/is-there-a-way-to-list-all-configurable-alternatives-symlinks-for-similar-com

Ale ja nadal wątpliwości, dlaczego to robisz. Tak więc, jeśli potrafisz wyjaśnić pierwotne wymagania, bardzo by to pomogło. To za unikanie X-Y problem.

+0

+1 Jest to przydatne dla użytkowników systemu Linux, ale w przypadku testów nie działa zgodnie z oczekiwaniami. Szukam rozwiązania Windows i Linux dla projektu, choć nie jest to jedno.Na szczęście, znalazłem rozwiązanie na własną rękę w momencie wydania. – Speentie8081

+0

W końcu, jakie było twoje rozwiązanie? Interesuje mnie. – FaithReaper

+0

Umieściłem najbardziej aktualny kod, którego używam jako zmianę do pytania. – Speentie8081

0

Twoje pytanie jest nieco niejasne, ale jeśli starasz się znaleźć aktualny katalog z poziomu bieżącego procesu, po prostu zrób

new File("").getAbsoluteFile().getAbsolutePath();