File IO in Java 8 - Part I
In Java8, several changes are incorporated with regards to File IO operation, Lets briefly explore each one of those.
Paths
Paths are starting point of File I/O operations. Get an path with Paths.get method
eg -
Path p1 = Paths.get("eg-file.txt");
Path p2 = Paths.get("/usr/temp/eg-file.txt");
Path p3 = Paths.get("C:\\temp\\eg-file.txt");
note: as java has predefined meaning for single backlash hence adding the double backslash.
In the below example, lets explore methods associated with Path class, such as getFileName(), toAbsolutePath(), getRoot()…etc
package fileOperations;
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathUsageExample {
public static void main(String[] args){
Path p1 = Paths.get("C:\\temp\\eg.txt");
//Simple Path : C:\temp\eg.txt
System.out.println("Simple Path : " + p1.toString());
//Get Absolute Path : C:\temp\eg.txt
Path p2 = p1.toAbsolutePath();
System.out.println("Absolute Path : "+p2.toString());
//Get File name : eg.txt
System.out.println("getFileName : "+ p2.getFileName());
//Get Name : temp
System.out.println("getName : "+ p2.getName(0));
//Get Name Count : 2
System.out.println("getNameCount : "+p2.getNameCount());
//Sub path : temp\eg.txt
System.out.println("subpath(0,2) : "+ p2.subpath(0,2));
//Get Parent : C:\temp
System.out.println("getParent : "+ p2.getParent());
//Get Root : C:\
System.out.println("getRoot :"+ p2.getRoot());
}
}
Reading File - Fetching Text Files as Stream of Strings -
with using Files.lines method, we can fetch the file content as Stream of strings. All stream operations such as map, filter, collect can be used.
Stream<String> lines = Files.lines(somePath);
By default Files.lines method uses UTF-8 charset , if in case different characterset is needed then method can be called with additional parameter - specifiedCharSet as in below
Stream<String> lines = Files.lines(“C:\\temp\\hiragana.txt”, “SHIFT-JIS”);
As its streams with I/O sources , it needs to be closed, it can be combined with try with resources statement and close() at end.
Example -
public static void main(String[] args) throws Exception {
String inputFile = "C:\\temp\\employee_names.txt";
String outputFile = "C:\\temp\\employee_name_starting_with_M.txt";
List<String> names = Files.lines(Paths.get(inputFile))
.filter(e -> (e.startsWith("m") || e.startsWith("M")))
.map(e -> e.toUpperCase())
.sorted()
.collect(Collectors.toList());
Files.write(Paths.get(outputFile), names, Charset.defaultCharset());
System.out.printf(" wrote %s words to %s /n", names.size(), outputFile);
}
Input text file :
Output Text File:
Writing File -
we have two versions of writing file.
Files.write(somePath, lines, someCharSet, someOption); // can write all lines in single call
Files.write(somePath, fileArray, someOption); // can write all bytes in single call
In our previous example, after file processing, we’re writing it output text file, providing the outputFileName as first param, and content as second param(in our case its names) and charSet as third param to write method call.
String inputFile = "C:\\temp\\employee_names.txt";
String outputFile = "C:\\temp\\employee_name_starting_with_M.txt";
List<String> names = Files.lines(Paths.get(inputFile))
.filter(e -> (e.startsWith("m") || e.startsWith("M")))
.map(e -> e.toUpperCase())
.sorted()
.collect(Collectors.toList());
Files.write(Paths.get(outputFile), names, Charset.defaultCharset());
we do have disadvantages in using the above write method, such that if we processing very large files, storing up all the data in memory as list at once creates huge memory footprint on our application. To avoid that, we can use buffered writing as its writes the data in blocks and its faster for very large files.
Eg -
Writer w = Files.newBufferedWriter(somePath, someCharSet);
w.write(
we’ll continue more on exploring about BufferedWriter, printWriter in part II of this series.