Methoden Path.toFile().canRead vs Path.isReadable

piro

Aktives Mitglied
Hallo zusammen,

wie der Title schon sage, habe ich beide Methoden verwendet und bin schlußendlich wieder bei
Java:
Path.toFile().canRead
aus Gründen der Performance und diesem Artikel.
java.nio.file.Files.isReadable() returns false on readable file - General discussion related to the NIO Project - ArchiveOrange

Habt ihr hier auch schon Erfahrung mitgemacht? Oder verwende ich die Methoden falsch.

Ich möchte gerne wissen, ob ich eine Datei lesen kann und möchte java.nio.file verwenden und nicht java.io.file.

Danke im Voraus.
Sven
 
Java:
Files.walkFileTree( dir, new SimpleFileVisitor<Path>() {
	
	@Override
	public FileVisitResult visitFile(Path dir, BasicFileAttributes bfa) {
		
		boolean nio = Files.isReadable( dir );
		boolean io = dir.toFile().canRead();
		if( nio != io ) {
			System.out.println( "NIO != IO" );
			System.out.println( "NIO: " + nio );
			System.out.println( "IO: " + io );
			try {
				Files.readAllBytes( dir );
				System.out.println( "NIO read success" );
			} catch( IOException e ) {
				System.out.println( "NIO read fail" );
			}
			try( FileInputStream fis = new FileInputStream( dir.toFile() );
				BufferedReader br = new BufferedReader( new InputStreamReader( fis ) ); ) {
				br.readLine();
				System.out.println( "IO read success" );
			} catch( IOException e ) {
				System.out.println( "IO read fail" );
				e.printStackTrace(); // wo genau der Fehler aufgetaucht ist
			}
		}
		return FileVisitResult.CONTINUE;
	}
	
	@Override
	public FileVisitResult visitFileFailed(Path dir, IOException e) {
		return FileVisitResult.CONTINUE;
	}
} );

Hab das über ganz C:/ laufen gelassen und nicht ein Treffer gekommen.

Die beiden sollten also mindestens zu 99,99% immer die gleichen Werte liefern.

E:
Das Programm war noch am Laufen, folgende Ausgabe auf der Konsole:

Code:
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
NIO != IO
NIO: false
IO: true
NIO read fail
IO read fail
 
Zuletzt bearbeitet:
Hier ist ein besserer Test, "ProgramData" ist anscheinend ein kritisches Verzeichnis, da landen lauter Treffer:

Java:
Path dir = Paths.get("C:", "ProgramData");
Files.walkFileTree( dir, new SimpleFileVisitor<Path>() {
	
	@Override
	public FileVisitResult visitFile(Path dir, BasicFileAttributes bfa) {
		
		boolean nio = Files.isReadable( dir );
		boolean io = dir.toFile().canRead();
		if( nio != io ) {
			System.out.println( "NIO != IO (" + dir + ")" );
			System.out.println( "NIO: " + nio );
			System.out.println( "IO: " + io );
			boolean nioTest;
			try {
				Files.readAllBytes( dir );
				nioTest = true;
			} catch( IOException e ) {
				nioTest = false;
			}
			boolean ioTest;
			try( FileInputStream fis = new FileInputStream( dir.toFile() ); ) {
				ioTest = true;
			} catch( IOException e ) {
				ioTest = false;
			}
			System.out.println( "NIO read success: " + nioTest );
			System.out.println( "IO read success: " + ioTest );
			System.out.println();
		}
		return FileVisitResult.CONTINUE;
	}
	
	@Override
	public FileVisitResult visitFileFailed(Path dir, IOException e) {
		System.err.println( e.getClass().getName() + ": " + e.getMessage() );
		return FileVisitResult.CONTINUE;
	}
} );
 
Ok, dann ist Path.toFile.canRead() zu bevorzugen. Danke für deine Bemühung. Ist ja auch schneller.

Dann werde ich mal versuchen immer Java.nio.file zu verwenden und deine Hinweise berücksichtigen
 
Dann habe ich deinen Output nicht verstanden, denn bei isReadable() kommt immer ein false. Was ja falsch ist.

Und mein gefundener Artikel bestätigt dies. Soll heißen, derzeit ist canRead() besser und vorallem schneller.
8800 Dateien in mehreren Unterverzeichnissen werden innerhalb von 10 sec gelesen im Gegensatz zu isReadable(), da braucht er fast eine Minute.

Bitte um Klärung?
 
Also wenn du das Beispiel nicht verstehst, würd ich mir ernsthaft Gedanken machen.
Und mal so nebenbei, hast du keinen Compiler? Zeig ein wenig Eigeninitiative, du kannst ganz einfach Tests schreiben, wie sowas:

Java:
private static long timeNIO = 0;
private static long timeIO = 0;

public static void main(String... args) {
	try {
		UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
	} catch( Exception e ) {
		e.printStackTrace();
	}
	Path dir = userDirChoice().toPath();
	try {
		Files.walkFileTree( dir, new SimpleFileVisitor<Path>() {
			
			@Override
			public FileVisitResult visitFile(Path dir, BasicFileAttributes bfa) {
				long before = System.currentTimeMillis();
				Files.isReadable( dir );
				long after = System.currentTimeMillis();
				timeNIO += after - before;
				return FileVisitResult.CONTINUE;
			}
			
			@Override
			public FileVisitResult visitFileFailed(Path dir, IOException e) {
				return FileVisitResult.CONTINUE;
			}
		} );
		Files.walkFileTree( dir, new SimpleFileVisitor<Path>() {
			
			@Override
			public FileVisitResult visitFile(Path dir, BasicFileAttributes bfa) {
				long before = System.currentTimeMillis();
				dir.toFile().canRead();
				long after = System.currentTimeMillis();
				timeIO += after - before;
				return FileVisitResult.CONTINUE;
			}
			
			@Override
			public FileVisitResult visitFileFailed(Path dir, IOException e) {
				return FileVisitResult.CONTINUE;
			}
		} );
	} catch( IOException e ) {
		e.printStackTrace();
	}
	System.out.println( "NIO duration: " + timeNIO );
	System.out.println( "IO duration: " + timeIO );
}

private static final File userDirChoice() {
	JFileChooser fc = new JFileChooser();
	fc.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY );
	fc.setMultiSelectionEnabled( false );
	if( fc.showOpenDialog( null ) != 0 )
		System.exit( 0 );
	return fc.getSelectedFile();
}

Ausgabe:
Code:
NIO duration: 16283
IO duration: 480

NIO dauert länger, bei wenigen Dateien sollte das nicht so sehr ins Gewicht fallen. Dafür ist NIO präzise, und wenn eine Datei nicht lesbar ist, gibt NIO false aus, File gibt manchmal true aus.
Du musst deinen Kompromiss finden.
 
Danke nochmal für deine Hilfe. Deinen Code habe ich verstanden. Hatte nur nicht so schnell gesehen, dass du nur eine Ausgabe hast, wenn die beiden Methoden Unterschiedlich sind.

Muss mal abwägen, was ich nehme. Bei meiner Anwendung muss ich nur checken, ob die Datei lesbar ist.

Danke nochmal.
Sven
 

Zurück
Oben