Monday, August 15, 2016

How to process text files through the console

In the example below, you are going to see a way of writing a code that processes text files in java and does the reading, copying, moving, deleting, listing or searching operations.

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

// implements a simplified version of "type" command provided in Windows given
// a text file name(s) as argument, it prints the content of the text file(s) on console 
class Type {
public static void main(String[] files) {
if (files.length == 0) {
System.err.println("pass the name of the file(s) as argument");
System.exit(-1);
}
// process each file passed as argument
for (String file : files) {
// try opening the file with FileReader
try (FileReader inputFile = new FileReader(file)) {
int ch = 0;
// while there are characters to fetch, read, and print the
// characters when EOF is reached, read() will return -1,
// terminating the loop
while ((ch = inputFile.read()) != -1) {
// ch is of type int - convert it back to char
// before printing
System.out.print((char) ch);
}
} catch (FileNotFoundException fnfe) {
// the passed file is not found …
System.err.printf("Cannot open the given file %s ", file);
} catch (IOException ioe) {
// some IO error occurred when reading the file …
System.err.printf("Error when processing file %s… skipping it", file);
}
// try-with-resources will automatically release FileReader object
}
}
}

Yet, a better way to do the same thing using streams:

import java.io.IOException;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.stream.Stream;

// implements a simplified version of "type" command provided in Windows; 
// given a text file name(s) as argument, it prints the content of the file(s) 

class Type {
private static void processFile(String file) {
try (Stream<String> lines = Files.lines(Paths.get(file))) {
lines.forEach(System.out::println);
} catch (IOException ioe) {
System.err.println("IOException occurred when reading the file... exiting");
System.exit(-1);
}
}

public static void main(String[] files) throws IOException {
if (files.length == 0) {
System.err.println("pass the name of the file(s) as argument");
System.exit(-1);
}
// process each file passed as argument
Arrays.stream(files).forEach(Type::processFile);
}
}

That is it, now, it suffices that you compile your code using the command: javac Type.java.
Then, execute the compiled file using the command: java Type [name of the files you want to read].

On the other hand, if you want to copy a text file into another destination you may make use of the code below:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

// implements a simplified version of "copy" command provided in Windows
// syntax: java Copy SrcFile DstFile 
// copies ScrFile to DstFile; over-writes the DstFile if it already exits 
class Copy {
public static void main(String[] files) {
if (files.length != 2) {
System.err.println("Incorrect syntax. Correct syntax: Copy SrcFile DstFile");
System.exit(-1);
}
String srcFile = files[0];
String dstFile = files[1];
// try opening the source and destination file
// with FileReader and FileWriter
try (BufferedReader inputFile = new BufferedReader(new FileReader(srcFile));
BufferedWriter outputFile = new BufferedWriter(new FileWriter(dstFile))) {
int ch = 0;
// while there are characters to fetch, read the characters from
// source stream and write them to the destination stream
while ((ch = inputFile.read()) != -1) {
// ch is of type int - convert it back to char before
// writing it
outputFile.write((char) ch);
}
// no need to call flush explicitly for outputFile - the close()
// method will first call flush before closing the outputFile stream
} catch (FileNotFoundException fnfe) {
// the passed file is not found …
System.err.println("Cannot open the file " + fnfe.getMessage());
} catch (IOException ioe) {
// some IO error occurred when reading the file …
System.err.printf("Error when processing file; exiting ... ");
}
// try-with-resources will automatically release FileReader object
}
}

Now, it suffices that you compile your code and execute it giving two arguments the source and the destination file. Yet, a better way to do the copying operation is by using the Paths utility as follows:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class FileCopy {
    public static void main(String[] args) {
        if(args.length != 2){
            System.out.println("usage: FileCopy <source-path> <destination-path>");
            System.exit(1);
        }
        Path pathSource = Paths.get(args[0]);
        Path pathDestination = Paths.get(args[1]);
        try {
            Files.copy(pathSource, pathDestination);
            System.out.println("Source file copied successfully");                
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Moreover, sometimes you might want to move a file to another destination rather than copying it. The following code represents a way to do so:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class FileMove {
public static void main(String[] args) {
if (args.length != 2) {
System.out.println("usage: FileMove <source-path> <destination-path>");
System.exit(-1);
}
Path pathSource = Paths.get(args[0]);
Path pathDestination = Paths.get(args[1]);
try {
Files.move(pathSource, pathDestination, StandardCopyOption.REPLACE_EXISTING);
System.out.println("Source file moved successfully");
} catch (IOException e) {
e.printStackTrace();
}
}
}

In order to remove a file, here is one way of proceding:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class FileDelete {
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("usage: FileDelete <source-path>");
System.exit(1);
}
Path pathSource = Paths.get(args[0]);
try {
Files.delete(pathSource);
System.out.println("File deleted successfully");
} catch (IOException e) {
e.printStackTrace();
}
}
}

In order to list files within the current directory, you might use the following code:

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;
import java.util.stream.Stream;

class ListFiles {
public static void main(String[] args) throws IOException {
try (Stream<Path> entries = Files.list(Paths.get("."))) {
entries.forEach(System.out::println);
}
}
}

Another useful case is to find files with a specific extension within the current directory, here is a smart manner to look for .class files using streams:

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.function.BiPredicate;
import java.util.stream.Stream;

class FindFiles {
public static void main(String[] args) throws IOException {
BiPredicate<Path, BasicFileAttributes> predicate = (path, attrs) -> attrs.isRegularFile()
&& path.toString().endsWith("class");
try (Stream<Path> entries = Files.find(Paths.get("."), 4, predicate)) {
entries.limit(100).forEach(System.out::println);
}
}
}

No comments:

Post a Comment