ZOFTINO.COM android and web dev tutorials

Java File Input Output Using NIO2 API

To access files, file attributes and file system, Java provides classes and interfaces (new IO API called NIO2) which exist in the java.nio.file and java.nio.file.attribute packages. The main classes, Path and Files, make it easy to perform operations on files and do file manipulations.

Files class provides static methods to create, copy, move and delete files and directories, read and write file attributes, read and write files using IO streams and channels, etc.

Table of Contents

Path

Path class is used to represents a file or directory. Path object can be created using Paths utility class.

Path p = Paths.get("/Project/ZOFTINO");

You can use var arg get method of Paths to create Path object.

Path p = Paths.get("Project", "ZOFTINO");

Path has various methods such as getNameCount to get number of elements, getRoot to get root component as Path, toFile to convert the path object to file object and toUri to convert the path object to URI object. You can get sub path using subpath() method and passing beginning and ending indices.

Method resolve can be used to create new path object as shown below.

		Path p = Paths.get("/Project/ZOFTINO");
		
		Path docs = p.resolve("docs");
		System.out.println(docs.toString());

Output:

\Project\ZOFTINO\docs

Method normalize gives you a different path by removing .. and preceding name from path.

		Path p = Paths.get("/Project/ZOFTINO/../doc");
		
		Path npath = p.normalize();
		System.out.println(npath.toString());

Output:

\Project\doc

Files

Files class provides static methods to perform various operations on file system, files and directories.

Method createDirectories creates all the directories of the path object passed to it.

	Path p = Paths.get("/dev/java/core");
	
	try {
		Files.createDirectories(p);
	} catch (IOException e) {
		e.printStackTrace();
	}

Similarly, you can use createFile method to create the file that the path which is passed to the method as an argument represents.

		Path p = Paths.get("/dev/java/core/test.txt");	
		Files.createFile(p);

You can delete a file using methods delete() or deleteIfExists() passing path argument to the methods. You can check existence of a file using exists() method.

		Path p = Paths.get("/dev/java/core/test.txt");		
		if(Files.exists(p)) {
			System.out.println("file exists");
		}

You get file type (MIME type) using probeContentType() method of Files class.

		Path deals = Paths.get("/dev/java/core/app/deals.txt");	
		
		try {
		    String type = Files.probeContentType(deals);
		    System.out.println("file MIME type: "+type);
		} catch (IOException ex) {
		    System.out.println(ex);
		}

File Metadata Management

Files class provides various methods which can be used to read and update file metadata such as size, last modified date, owner and other attributes.

You can set last modified time of a file by using setLastModifiedTime() method and passing path and FileTime objects arguments to the method. You can create FileTime object using fromMillis or other static methods.

	Path p = Paths.get("/dev/java/core/test.txt");		
	FileTime lastModifiedTime = 
			FileTime.fromMillis(System.currentTimeMillis());
	try {
		Files.setLastModifiedTime(p, lastModifiedTime);
	} catch (IOException e) {
		e.printStackTrace();
	}

You can set attributes of a file using setAttribute method and get attributes of a file using readAttributes methods. To set attributes of a file, you need to pass path object which represents the file, attribute name and value to setAttributes method. To read attributes of a file, you need to pass path and attributes class such as BasicFileAttributes, DosFileAttributes and PosixFileAttributes to the readAttributes method.

		Path p = Paths.get("/dev/java/core/test.txt");			
		try {
			Files.setAttribute(p, "dos:readonly", true);
			Files.setAttribute(p, "dos:hidden", false);				
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			DosFileAttributes attris = 
					Files.readAttributes(p, DosFileAttributes.class);
			System.out.println(attris.isReadOnly());
			
		} catch (IOException e) {
			e.printStackTrace();
		}

You can set file owner by using setOwner method and passing path and user principal objects as arguments to the method. You can get user principal object using UserPrincipalLookupService object which can be obtained using the FileSystem object as shown below.

		Path offers = Paths.get("/dev/java/core/offers.txt");
		
		UserPrincipal owner;
		try {
			owner = offers.getFileSystem().getUserPrincipalLookupService()
			        .lookupPrincipalByName("srurao");
			Files.setOwner(offers, owner);
		} catch (IOException e) {
			e.printStackTrace();
		}

You can add your own attributes to files using UserDefinedFileAttributeView object which can be obtained by calling getFileAttributeView() method of Files class passing path and UserDefinedFileAttributeView class arguments to it.

		Path offers = Paths.get("/dev/java/core/app/offers.txt");
		
		UserDefinedFileAttributeView view = Files
					.getFileAttributeView(offers, 
							UserDefinedFileAttributeView.class);
		try {
			view.write("lang",
					Charset.forName("UTF-8").encode("eng"));
		} catch (IOException e) {

		}

Below example shows how to read custom file attributes.

	Path offers = Paths.get("/dev/java/core/app/offers.txt");
	
	UserDefinedFileAttributeView view = Files
				.getFileAttributeView(offers, 
						UserDefinedFileAttributeView.class);
	
	ByteBuffer bb = ByteBuffer.allocate(15);
	try {
		view.read("lang", bb);
		bb.flip();
		String lang = Charset.forName("UTF-8").decode(bb).toString();
		System.out.println(lang);
	} catch (IOException e) {
		e.printStackTrace();
	}

You can get metadata about file store using FireStore object which can be obtained using getFileStore() method.

		Path offers = Paths.get("/dev/java/core/app/offers.txt");
		try {
			FileStore fs = Files.getFileStore(offers);
			
			System.out.println("total space: "+fs.getTotalSpace());
			System.out.println("Unallocated space: "+fs.getUnallocatedSpace());
			
		} catch (IOException e1) {
			e1.printStackTrace();
		}

Copying File or Directory

A file can be copied to output stream, bytes from input stream can be copied to a file and a file can be copied to a target file using static method copy() of Files class. Below code shows copying input stream to a file.

		String offer = "upto 44% off on bags";
		InputStream is = new ByteArrayInputStream(offer.getBytes());

		Path offersFile = Paths.get("/dev/java/core/offers.txt");
		
	    CopyOption[] cOptions = 
	             new CopyOption[] { StandardCopyOption.REPLACE_EXISTING };             
		
		try {
			Files.copy(is, offersFile, cOptions);
		} catch (IOException e1) {
			e1.printStackTrace();
		}

Copying a file to an output stream example.

		Path offers = Paths.get("/dev/java/core/offers.txt");
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		
		try {
			Files.copy(offers, os);
			String deals = new String(os.toByteArray());
			System.out.println(deals);
		} catch (IOException ex) {
			ex.printStackTrace();
		}

To copy a file to a target file, you need to pass source path, target path and copy options arguments to the copy method. You can create CopyOption array using StandardCopyOption enum values REPLACE_EXISTING and COPY_ATTRIBUTES.

		Path offers = Paths.get("/dev/java/core/offers.txt");
		Path oldOffers = Paths.get("/dev/java/core/old_offers.txt");
	    CopyOption[] copyOptions = 
	             new CopyOption[] { StandardCopyOption.REPLACE_EXISTING };
		try {
			Files.copy(offers, oldOffers, copyOptions);
		} catch (IOException ex) {
			ex.printStackTrace();
		}

Moving File or Directory

You can move a file or directory to a target using move() method and passing source and target paths and copy options as argument to it.

		Path offers = Paths.get("/dev/java/core/offers.txt");
		Path oldOffers = Paths.get("/dev/java/core/app/offers.txt");
	    CopyOption[] copyOptions = 
	             new CopyOption[] { StandardCopyOption.ATOMIC_MOVE };
		try {
			Files.move(offers, oldOffers, copyOptions);
		} catch (IOException ex) {
			ex.printStackTrace();
		}

Reading Complete File

Complete content of small files can be read using readAllBytes() method of Files class. The method returns byte array.

		Path offers = Paths.get("/dev/java/core/app/offers.txt");
		
		try {
			byte cont[] = Files.readAllBytes(offers);
			System.out.println("File content: "+ new String(cont));
		} catch (IOException ex) {
			ex.printStackTrace();
		}

You can also use readAllLines() methods to read complete file. This is useful reading small text files. The methods returns List object containing all lines of the file.

	List<String> lines = Files.readAllLines(offers, 
			Charset.defaultCharset());
	
	for(String line : lines) {
		System.out.println(line);
	}

Writing Bytes and Lines to a File

You can write byte array to a file using write method of Files class. Write method takes file path object, byte array and optional OpenOption array as arguments. Enum StandardOpenOption contains possible values for open option, such as APPEND (appends content to file), CREATE(creates a new file if doesn't exist), CREATE_NEW (creates a new file, if exists operation will fail), READ (open file for reading), TRUNCATE_EXISTING (existing file opened for WRITE access is truncated to 0 length), and WRITE (open for writing).

		Path deals = Paths.get("/dev/java/core/app/deals.txt");
		
		String dealsS = "upto 20% off on tabs,flat 10% off on mobiles";
		byte dealsB[] = dealsS.getBytes();
		
		OpenOption[] openOptions = 
	             new OpenOption[] {StandardOpenOption.CREATE_NEW };
		try {
			Files.write(deals, dealsB, openOptions);
		} catch (IOException e) {
			e.printStackTrace();
		}

You can write iterable object which contains CharSequence object to a file using write method of Files class. The method takes path, iterable object, charset and open options as arguments. For example you can write list or set of strings to a file using write method.

		Path deals = Paths.get("/dev/java/core/app/deals.txt");
		
		List<String> stores = new ArrayList<String>();
		stores.add("amazon");
		stores.add("walmart");
		stores.add("macys");
		
		OpenOption[]options = 
	             new OpenOption[] {StandardOpenOption.APPEND };
		try {
			Files.write(deals, stores, Charset.forName("UTF-8"), options);
		} catch (IOException e1) {
			e1.printStackTrace();
		}

Reading File using IO Stream

You can read a file using InputStream object which can be obtained by calling newInputStream() method on Files class and passing path object and open options array arguments to it. For more information about IO byte streams, see Java IO byte streams tutorial.

	Path deals = Paths.get("/dev/java/core/app/deals.txt");
	OpenOption[] options = 
			new OpenOption[] {StandardOpenOption.READ };

	try (InputStream in = Files.newInputStream(deals, options);
					BufferedReader reader =	new BufferedReader(
							new InputStreamReader(in))) {
		String content = null;
		while ((content = reader.readLine()) != null) {
			System.out.println(content);
		}
	} catch (IOException x) {
		System.out.println(x.toString());
	}

Writing to a File using IO Stream

To write bytes to a file using IO stream, you need to get OutputStream object by calling newOutputStream() method on Files class passing path and open options object arguments to it. See Java IO byte streams tutorial to know about IO byte streams.

		Path deals = Paths.get("/dev/java/core/app/deals.txt");
		OpenOption[] options = 
				new OpenOption[] {StandardOpenOption.CREATE };
		String coupon = "40% off on all items";
		byte cpnb[] = coupon.getBytes();

		try (OutputStream out = new BufferedOutputStream(
				Files.newOutputStream(deals, options))) {
			
			out.write(cpnb, 0, cpnb.length);
			
		} catch (IOException ex) {
			System.out.println(ex);
		}	

Reading Text File using Reader

You can read a text file using Reader object which can be obtained by calling newBufferedReader() method on Files class and passing path object, charset and open options array arguments to it. For more information about IO character streams see Java IO character streams tutorial.

		try (BufferedReader reader = Files.
				newBufferedReader(deals, Charset.forName("UTF-16"))) {
		    String line = null;
		    while ((line = reader.readLine()) != null) {
		        System.out.println(line);
		    }
		} catch (IOException ex) {
		    System.out.println(ex);
		}

Writing Text to File using Writer

To write text to a file using Writer, you need to get BufferedWriter object by calling newBufferedWriter() method on Files class passing path, charset and open options object arguments to it. See Java IO character streams tutorial to know about IO byte streams.

		Path deals = Paths.get("/dev/java/core/app/deals.txt");
		OpenOption[] options = 
				new OpenOption[] {StandardOpenOption.CREATE };
		String coupon = "best deals on fashion, upto 80% off";

		try (BufferedWriter writer = Files.
				newBufferedWriter(deals, Charset.defaultCharset(), options)) {
		    writer.write(coupon, 0, coupon.length());
		} catch (IOException x) {
		    System.err.format("IOException: %s%n", x);
		}

Reading a File using Channel

You can read a file efficiently using Channel and Buffer objects. Method newByteChannel() of Files class returns instance of ReadableByteChannel, WritableByteChannel or SeekableByteChannel channel object depending on the set of open options passed to the method. SeekableByteChannel object can be used for both reading a file and writing to a file.

	Path deals = Paths.get("/dev/java/core/app/deals.txt");
	OpenOption[] options = new OpenOption[] {
					StandardOpenOption.CREATE,
					StandardOpenOption.READ,
					StandardOpenOption.WRITE};

	try (SeekableByteChannel sbc = Files.newByteChannel(deals, options)) {			
		ByteBuffer bb = ByteBuffer.allocate(10);
		while (sbc.read(bb) > 0) {
			bb.flip();
			System.out.print(Charset.forName("UTF-8").decode(bb).toString());
			bb.rewind();
		}
	} catch (IOException ex) {
		System.out.println(ex);
	}

If you pass only READ open option to newByteChannel() method, you can get ReadableByteChannel object which can only be used to read files.

	OpenOption[] options = 
			new OpenOption[] {StandardOpenOption.READ};
	
	ReadableByteChannel sbc = Files.newByteChannel(filePath, options)

Writing to a File using Channel

You can efficiently write to a file using Channel and Buffer objects. Method newByteChannel() of Files class returns instance of WritableByteChannel or SeekableByteChannel channel object depending on the set of open options passed to the method. You have to use ByteBuffer for reading and writing data with channels, see Java NIO tutorial for more information.

		Path deals = Paths.get("/dev/java/core/app/deals.txt");	
		OpenOption[] options = 
				new OpenOption[] {StandardOpenOption.WRITE,
						StandardOpenOption.APPEND};
		
	    String stores = "amazon, nordstorm, macys, sears, jcpenny, walmart, costco";
	    byte data[] = stores.getBytes();
	    ByteBuffer bb = ByteBuffer.wrap(data);	   

	    try (SeekableByteChannel sbc = Files.newByteChannel(deals, options)) {
	      sbc.write(bb);
	    } catch (IOException ex) {
	      System.out.println(ex);
	    }

Other Tutorials Related to IO