2012-12-05 18 views
11

Szukałem w pobliżu, próbując znaleźć sposób na ustalenie, czy plik jest skrzyżowaniem, czy nie, i nie znalazłem zadowalających odpowiedzi.Sprawdź, czy plik jest złączem (w systemie Windows), czy nie?

Pierwszą rzeczą próbowałem było:

Files.isSymbolicLink(aPath) 

Wykrywa tylko linki symboliczne nie pliki zwane skrzyżowań w systemie Windows.

próbował również rozwiązanie proponowane tutaj (przy użyciu biblioteki jna): Stackoverflow question (3249117) , ale nigdy nie wrócił prawda na żadnym z plików znam się skrzyżowaniach.

Jedynym sposobem znalazłem aby określić, które pliki są złącza jest następujący przebieg polecenie w wierszu polecenia systemu Windows:

DIR /S /A:L 

Na moim komputerze zwraca 66 foldery ubezpieczeniowy Files.isSymbolicLink (aPath) powrócił tylko 2. Więc przypuszczam, że mógłbym znaleźć sposób na wykorzystanie tego, ale nie sądzę, że byłoby to bardzo skuteczne przy przechodzeniu przez filetree.

Czy można to zrobić za pomocą standardowej biblioteki Java lub alternatywnie JNA?

Odpowiedz

4

Jeśli możesz napisać natywny kod w JNA, możesz bezpośrednio wywołać funkcję Win32 API GetFileAttributes() i sprawdzić flagę FILE_ATTRIBUTE_REPARSE_POINT (złącza są zaimplementowane jako punkty ponownej analizy).

Aktualizacja: W celu rozróżnienia pomiędzy różnymi rodzajami punktów ponownej analizy, trzeba retreive się ReparseTag rzeczywistego punktu ponownej analizy. W przypadku punktu połączenia zostanie ustawiony na IO_REPARSE_TAG_MOUNT_POINT (0xA0000003).

Istnieją dwa sposoby retreive się ReparseTag:

  1. Korzystając DeviceIoControl() z kodem FSCTL_GET_REPARSE_POINT kontroli w celu uzyskania REPARSE_DATA_BUFFER struct, który jako pole ReparseTag. Można zobaczyć przykład implementacji IsDirectoryJunction() użyciu tej techniki w następującym artykule:

    NTFS Hard Links, Directory Junctions, and Windows Shortcuts

  2. Zastosowanie FindFirstFile() do uzyskania WIN32_FIND_DATA struct. Jeśli ścieżka ma atrybut FILE_ATTRIBUTE_REPARSE_POINT, pole dwReserved0 będzie zawierało ReparseTag.

+0

Dziękuję, nigdy tak naprawdę nie korzystałem z JNA, z wyjątkiem kopiowania i wklejania kodu, ale jeśli jest to jedyny sposób, jak sądzę, lepiej się uczę. – Martin

+0

To, co sugerujesz, przypomina sugestię w zamieszczonym przeze mnie linku, byłoby bardzo pomocne, gdybyś mógł podać przykład sprawdzenia flagi reparse. – Martin

+0

'FILE_ATTRIBUTE_REPARSE_POINT' jest zdefiniowany jako' 0x400', więc przykładowy kod, z którym się łączysz, sprawdza specjalnie 'FILE_ATTRIBUTE_REPARSE_POINT'. –

7

Nie może być sposób, aby to zrobić bez JNA, jeśli masz prawo Java, takich jak Oracle JDK 8. Jest sprytny, może przestać do pracy, ale ....

Ty można dostać BasicFileAttributes interfejsu związanego z linku:

BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS); 

może się zdarzyć, że ta implementacja interfejsu jest klasą sun.nio.fs.WindowsFileAttributes. I ta klasa ma metodę isReparsePoint, która zwraca wartość true zarówno dla punktów połączenia, jak i dowiązań symbolicznych.Więc można spróbować użyć refleksji i wywołać metodę:

boolean isReparsePoint = false; 
    if (DosFileAttributes.class.isInstance(attr)) 
     try { 
      Method m = attr.getClass().getDeclaredMethod("isReparsePoint"); 
      m.setAccessible(true); 
      isReparsePoint = (boolean) m.invoke(attr); 
     } catch (Exception e) { 
      // just gave it a try 
     } 

Teraz tylko można dowiedzieć się, czy naprawdę jest to link symboliczny: Files.isSymbolicLink(path)

Jeśli jej nie jest, ale jest to ponownej analizy punkt, to jest to skrzyżowanie.

+0

Możesz zapisać potrzebę kroku 'Files.isSylmbolicLink (ścieżka)', odbijając refleksyjnie pole 'parseTag' w' WindowsFileAttributes' Złącze będzie miało wartość -1610612733 (i dowiązanie symboliczne -1610612724), Po prostu zastąp to, co jest w bloku 'try' z tym:' Field field = attr.getClass(). getDeclaredField ("reparseTag"); field.setAccessible (true); int parseTag = (int) field.get (attr); boolean isJunction = parseTag == -1610612733; ' – Javaru

4

Z J2SE 1.7 użycie Java NIO

/** 
* returns true if the Path is a Windows Junction 
*/ 
private static boolean isJunction(Path p) { 
    boolean isJunction = false; 
    try { 
     isJunction = (p.compareTo(p.toRealPath()) != 0); 
    } catch (IOException e) { 
     e.printStackTrace(); // TODO: handleMeProperly 
    } 
    return isJunction; 
} 
+0

wydaje się, że to nie działa. Funkcja toRealPath() jest taka sama jak sama ścieżka dla skrzyżowania. –

+0

Tak właśnie oczekuje się na skrzyżowaniu. –

+0

Ten kod nie działa, prawda? Dla skrzyżowania p.compareTo (p.toRealPath()) wynosi 0, jak ustaliłeś i jak zobaczyłem w teście. –

0

podczas systemie Windows atrybuty skrzyżowania mają isSymbolicLink() == false jest isOther() == true. Możesz więc zrobić coś takiego:

BasicFileAttributes attrs = Files.readAttributes(aPath, BasicFileAttributes.class); 
boolean isJunction = isWindows && attrs.isDirectory() && attrs.isOther(); 
Powiązane problemy