2010-01-21 14 views
16

Sto provando a utilizzare il seguente codice per accedere a un byte con offset di 50 byte in un disco non elaborato.Come accedere a dati grezzi specifici su disco da java

randomAccessFile = new RandomAccessFile("C:", "r"); 
randomAccessFile.seek(50); 
byte[] buffer = new byte[1]; 
randomAccessFile.read(buffer); 

Ma tutto ciò che ottengo è il seguente errore:

java.io.FileNotFoundException: C: (Acceso denegado) 
at java.io.RandomAccessFile.open(Native Method) 
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:212) 
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:98) 
at pru.lseek.main(lseek.java:26) 

Esiste un modo per accedere a un byte di preciso in un'unità da Java?

+0

aggiornato la mia risposta – stacker

risposta

4

RandomAccessFile non è destinata ad aprire le directory di manipolare le voci, è necessario creare o rimuovere i file. "Acceso denegado" significa probabilmente accesso negato. Per fare ciò, è necessario JNI.

EDIT: Quello che stai cercando di fare, è davvero complicato, non esiste un modo comune per farlo. È possibile accedere al settore harddisc per settore, ma in questo caso si dovrebbe interpretare la sua struttura, che ovviamente dipende dal file system, FAT, NTFS, HPFS, ecc.

+0

provando attraverso JNI, ma senza fortuna: fp = fopen ("c:", "r")) <- non dà errore fseek (fp, i, SEEK_SET) <- non dà errore getc (fp) <- restituire sempre gli stessi dati qualunque sia il parametro i per fseek è – user178973

+0

Guarda qui come leggere i settori su disco: http://www.codeguru.com/cpp/wp/system/misc/article.php/c5765/ – stacker

+0

Grazie mille !! che risolve il mio problema: fp = fopen ("\\\\. \\ C:", "r")) Ora devo solo creare una libreria JNI, ma è curioso che nessuno lo abbia ancora creato. – user178973

3

Sotto Linux è possibile provare ad aprire /dev/<device>, ad es. /dev/hda o /dev/sdb2. Ciò ti consentirà di accedere a un disco non elaborato (o solo a una partizione), ma richiede che tu disponga dei diritti appropriati, tuttavia un utente "normale" non li possiede.

+0

Questo è quello che sto cercando di emulare. f = open ("/ dev/sda", O_RDONLY); – user178973

1

In Unix, è possibile leggere/scrivere dai file /dev. (Non sono sicuro)

In Windows, penso che sia necessario leggere/scrivere settori del disco tramite JNI (Java Native Interface). Chiama alcune librerie C per parlare al sistema operativo.

Aggiornamento

: nella libreria C, potrebbe essere necessario utilizzare Win32API per ottenere l'handle del file, ad esempio la funzione CreateFile(..).

https://metacpan.org/pod/Win32API::File

http://jan.newmarch.name/ssw/files/win32.html

+0

Bene, supponendo che creerò una libreria JNI, non so quale sia il primo parametro da passare nella funzione C "aperta": f = open ("C:", O_RDONLY); ??? – user178973

1

Java può accedere solo ai file. Unix ha il concetto di "dispositivi raw" come file nella directory/dev, quindi quello che vuoi è possibile lì. Ma non su Windows, perché non ha una tale rappresentazione di file dei dati HD grezzi.

+0

Come forse saprai, Windows ha anche i suoi metodi per accedere ai dispositivi raw, usando qualcosa chiamato "file UNC" o "percorsi UNC". Sono equivalenti ai percorsi di rete per l'accesso a risorse remote, ad es. '\\ risorsa', ma è necessario fare riferimento alla propria macchina usando' \\. \ resource', essendo risorsa, ad esempio 'PhysicalDrive0'. – Azurlake

1

In Windows è necessario accedere all'identificatore di dispositivo non elaborato come un file. Dovrebbe funzionare se si passa nel file "\\. \ C:", si sta utilizzando il nome UNC del dispositivo \. \ C: (\. Indica questa macchina).

per Vista e poi non credo che funzionerà correttamente in quanto vi sono meccanismi in atto per impedire l'accesso prima al disco per qualcosa di diverso da driver di periferica (non citare me su questo)

16

I Stavo cercando da solo la possibilità di accedere a dati grezzi da un disco fisico. E ora che ho avuto modo di funzionare, voglio solo dirti come. È possibile accedere ai dati su disco prima direttamente dall'interno di java ... basta eseguire il seguente codice con privilegi di amministratore:

File diskRoot = new File ("\\\\.\\PhysicalDrive0"); 
    RandomAccessFile diskAccess = new RandomAccessFile (diskRoot, "r"); 
    byte[] content = new byte[1024]; 
    diskAccess.readFully (content); 

Così si otterrà il primo kB del vostro primo disco fisico sul sistema. Per accedere alle unità logiche, come sopra menzionato, basta sostituire "PhysicalDrive0" con la lettera di unità, ad es. 'D:'

oh sì ... ho provato con Java 1.7 su un sistema Win 7 ...

Basta dare uno sguardo alla denominazione di unità fisiche a http://support.microsoft.com/kb/100027/en-us

+0

Grazie per questo. Funziona. Ho fatto lo stesso usando BufferedInputStream. Basta aprire il tuo programma o CLI con privilegi amministrativi. Ho usato anche l'oggetto File, tuttavia il metodo exist() non restituirà un risultato positivo, quindi fai attenzione. – mikato

+0

Come concedere privilegi amministrativi. Rispondere –

1

@hunsricker: notare che l'accesso ai dispositivi prime richiedono alcuni privilegi (dipende dal drive: rimovibile o no/dipende dal file system per WinXP: ISO9660 è permesso , FAT non lo è).

Si noti anche che la dimensione della lettura non importa (a seconda del sistema operativo): Su un file system iso9660, leggere (1024 byte) funziona su XP ma non riesce su Seven. Su Seven sembra che le letture debbano essere allineate a blocchi: leggere (2048 byte) funziona.

10

Se sei interessato a scrivendo a un volume grezzo sotto Windows, prova questo (richiede Java 7).

String pathname; 
    // Full drive: 
    // pathname = "\\\\.\\PhysicalDrive0"; 
    // A partition (also works if windows doesn't recognize it): 
    pathname = "\\\\.\\GLOBALROOT\\ArcName\\multi(0)disk(0)rdisk(0)partition(5)"; 

    Path diskRoot = (new File(pathname)).toPath(); 

    FileChannel fc = FileChannel.open(diskRoot, StandardOpenOption.READ, 
     StandardOpenOption.WRITE); 

    ByteBuffer bb = ByteBuffer.allocate(4096); 

    fc.position(4096); 
    fc.read(bb); 
    fc.position(4096); 
    fc.write(bb); 

    fc.close(); 

Ovviamente, è necessario assicurarsi che il dispositivo sia scrivibile e non accessibile/bloccato dal sistema. Assicurati inoltre che l'applicazione venga eseguita con i privilegi necessari (privilegi elevati).

Btw: l'utilizzo di new RandomAccessFile(drive, "rw") non sembra funzionare perché Java non apre l'handle del file in una modalità compatibile con i dispositivi non formattati (l'eccezione è java.io.FileNotFoundException (The parameter is incorrect)). Ma leggere funziona anche con RandomAccessFile.

+0

Ottima risposta; ti ringraziamo per aver affrontato WRITE usando specificamente le API NIO. –

Problemi correlati