How do I created tab delimited data file in Java?

The following code snippet show you how to create a tab delimited data file in Java. The tab character is represented using the \t sequence of characters, a backslash (\) character followed by the t letter. In the code below we start by defining some data that we are going to write to the file.

We create a PrintWriter object, passes a BufferedWritter created using the Files.newBufferedWriter() method. The countries.dat is the file name where the data will be written. Because we are using the try-with-resources the PrintWriter and the related object will be closed automatically when the file operation finishes.

package org.kodejava.io;

import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class TabDelimitedDataFile {
    public static void main(String[] args) throws IOException {
        List<String[]> data = new ArrayList<>();
        data.add(new String[]{"Afghanistan", "AF", "AFG", "004", "Asia"});
        data.add(new String[]{"Åland Islands", "AX", "ALA", "248", "Europe"});
        data.add(new String[]{"Albania", "AL", "ALB", "008", "Europe"});
        data.add(new String[]{"Algeria", "DZ", "DZA", "012", "Africa"});
        data.add(new String[]{"American Samoa", "AS", "ASM", "016", "Polynesia"});
        data.add(new String[]{"Andorra", "AD", "AND", "020", "South Europe"});
        data.add(new String[]{"Angola", "AO", "AGO", "024", "Africa"});
        data.add(new String[]{"Anguilla", "AI", "AIA", "660", "Americas"});
        data.add(new String[]{"Antarctica", "AQ", "ATA", "010", ""});
        data.add(new String[]{"Argentina", "AR", "ARG", "032", "Americas"});

        try (PrintWriter writer = new PrintWriter(
                Files.newBufferedWriter(Paths.get("countries.dat")))) {
            for (String[] row : data) {
                writer.printf("%1$20s\t%2$3s\t\t%3$3s\t\t%4$3s\t\t%5$s",
                        row[0], row[1], row[2], row[3], row[4]);
                writer.println();
            }
        }
    }
}

The output of the code snippet above are:

         Afghanistan     AF     AFG     004     Asia
       Åland Islands     AX     ALA     248     Europe
             Albania     AL     ALB     008     Europe
             Algeria     DZ     DZA     012     Africa
      American Samoa     AS     ASM     016     Polynesia
             Andorra     AD     AND     020     South Europe
              Angola     AO     AGO     024     Africa
            Anguilla     AI     AIA     660     Americas
          Antarctica     AQ     ATA     010     
           Argentina     AR     ARG     032     Americas

How do I read last n characters from a file?

In the following post you will learn how to read last n characters from a file. The JDK 7 introduces a new SeekableByteChannel interface which allows its implementation to change the position and the size of the byte channel. One of its implementation is the FileChannel class (java.nio.channels.FileChannel).

The FileChannel class make it possible to get hold the current position of where we are going to read from or write to a file. The code snippet below shows you how you can read the last 1000 characters from a log file.

package org.kodejava.io;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class FileReadLastNCharacters {
    public static void main(String[] args) {
        // Defines the path to the log file and creates a ByteBuffer.
        Path logPath = Paths.get("C:/tools/apache-tomcat-10.0.11/logs/catalina.out");
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        try {
            // Creates FileChannel and open the file channel for read access.
            FileChannel channel = FileChannel.open(logPath, StandardOpenOption.READ);

            // Read a sequence of bytes from the channel into the buffer starting
            // at given file position, which is the channel size - 1000. Because
            // we are going to read the last 1000 characters from the file.
            channel.read(buffer, channel.size() - 1000);
            System.out.println("Characters = " + new String(buffer.array()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

The steps in the code snippet above are:

  • Get the path to the log file.
  • Create a ByteBuffer, a buffer where the read bytes to be transferred.
  • Using the FileChannel.open() method we open a file to be read and return a FileChannel object.
  • The read() method of the FileChannel reads a sequence of bytes from the channel and transfer them to the given buffer starting and the position defined by channel.size() - 1000. This method returns the number of bytes read, possible zero, or -1 if the given position is greater than or equal to the file’s current size.
  • Print out the buffered string.

How to monitor file or directory changes?

package org.kodejava.io;

import java.io.IOException;
import java.nio.file.*;

import static java.nio.file.StandardWatchEventKinds.*;

public class FileWatchDemo {
    public static void main(String[] args) {
        try {
            // Creates a instance of WatchService.
            WatchService watcher = FileSystems.getDefault().newWatchService();

            // Registers the logDir below with a watch service.
            Path logDir = Paths.get("F:/Temp/");
            logDir.register(watcher, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);

            // Monitor the logDir at listen for change notification.
            while (true) {
                WatchKey key = watcher.take();
                for (WatchEvent<?> event : key.pollEvents()) {
                    WatchEvent.Kind<?> kind = event.kind();

                    if (ENTRY_CREATE.equals(kind)) {
                        System.out.println("Entry was created on log dir.");
                    } else if (ENTRY_MODIFY.equals(kind)) {
                        System.out.println("Entry was modified on log dir.");
                    } else if (ENTRY_DELETE.equals(kind)) {
                        System.out.println("Entry was deleted from log dir.");
                    }
                }
                key.reset();
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

To get the created, modified or deleted file you can see the following example: How to get the file name when using WatchService?.

How to get the file name when using WatchService?

package org.kodejava.io;

import java.io.IOException;
import java.nio.file.*;

import static java.nio.file.StandardWatchEventKinds.*;

public class WatchServiceGetFilename {
    public static void main(String[] args) {
        try {
            // Create a WatchService and register the logDir path with the
            // WatchService for ENTRY_CREATE.
            WatchService watcher = FileSystems.getDefault().newWatchService();
            Path logDir = Paths.get("F:/Temp");
            logDir.register(watcher, ENTRY_CREATE);

            while (true) {
                WatchKey key;
                try {
                    key = watcher.take();
                } catch (InterruptedException e) {
                    return;
                }

                for (WatchEvent<?> event : key.pollEvents()) {
                    if (event.kind() == ENTRY_CREATE) {
                        // Get the name of created file.
                        WatchEvent<Path> ev = cast(event);
                        Path filename = ev.context();

                        System.out.printf("A new file %s was created.%n",
                                filename.getFileName());
                    }
                }
                key.reset();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @SuppressWarnings("unchecked")
    private static <T> WatchEvent<T> cast(WatchEvent<?> event) {
        return (WatchEvent<T>) event;
    }
}

How to read file using Files.newBufferedReader?

In the snippet below you’ll learn to open file for reading using Files.newBufferedReader() method in JDK 7. This method returns a java.io.BufferedReader which makes a backward compatibility with the old I/O system in Java.

To read a file you’ll need to provide a Path and the Charset to the newBufferedReader() method arguments.

package org.kodejava.io;

import java.io.BufferedReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class FilesNewBufferedReader {
    public static void main(String[] args) {
        Path logFile = Paths.get("app.log");
        try (BufferedReader reader =
                     Files.newBufferedReader(logFile, StandardCharsets.UTF_8)) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

How to write file using Files.newBufferedWriter?

To open a file for writing in JDK 7 you can use the Files.newBufferedWriter() method. This method takes three arguments. We need to pass the Path, the Charset and a varargs of OpenOption.

For example, in the snippet below we pass the path of our log file, we use the StandardCharsets.UTF_8 charset, and we use the StandardOpenOption.WRITE to open a file for writing. If you want to open a file and append its contents instead of rewriting it you can use the StandardOpenOption.APPEND.

package org.kodejava.io;

import java.io.BufferedWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class FilesNewBufferedWriter {
    public static void main(String[] args) throws Exception {
        Path logFile = Paths.get("app.log");
        if (Files.notExists(logFile)) {
            Files.createFile(logFile);
        }

        try (BufferedWriter writer =
                     Files.newBufferedWriter(logFile, StandardCharsets.UTF_8,
                             StandardOpenOption.WRITE)) {

            for (int i = 0; i < 10; i++) {
                writer.write(String.format("Message %s%n", i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Because we use the StandardOpenOption.WRITE we have to make sure that the file to be written is exists. If the file is not available we will get error like java.nio.file.NoSuchFileException.

How do I move a file in JDK 7?

In the following code snippet you will learn how to move a file using the java.nio.file.Files helper class of JDK 7. This class simplify how you can move file. To move file you need to define the Path of the source and the target file.

We use the Files.move() method to move the file by passing the source and target path. We can also define the CopyOptions of the move process. For example to tell the move operation to replace the target file if the file already exist we can use the StandardCopyOption.REPLACE_EXISTING option. This option is a varargs, that means we can pass multiple options.

package org.kodejava.io;

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

import static java.nio.file.StandardCopyOption.*;

public class FileMoveDemo {
    public static void main(String[] args) {
        // Define the source and target of the file to be moved.
        Path source = Paths.get("F:/Temp/data.txt");
        Path target = Paths.get("F:/Temp/data.bak");

        try {
            // Move file from source to target using the defined
            // configuration (REPLACE_EXISTING)
            Files.move(source, target, REPLACE_EXISTING);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

How do I find files in a directory using DirectoryStream?

In this example we are going to learn to use the DirectoryStream, which part of java.nio.file package, to find files in a directory. We begin by creating a Path, the directory where the search will be conducted.

After that we create a DirectoryStream using Files.newDirectoryStream(). To create a directory stream we passed two arguments, the starting path and a glob expression. Below we use *.txt glob expression to filter all text files in the F:/Temp.

To get all the entries of the directory stream we can use a foreach loop as can be seen below. We iterate each entry, which is a Path object. And we print the entries file name using the getFileName() method.

package org.kodejava.io;

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

public class FindFilesInDirectory {
    public static void main(String[] args) {
        Path dir = Paths.get("F:/Temp");

        try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.txt")) {
            for (Path entry : stream) {
                System.out.println(entry.getFileName());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

You can also notice that in this example we are using the try-with-resource statement. This mean that the DirectoryStream will be closed appropriately when the process is done. This type of try statement is an improvement introduced in JDK 7.

How do I create and delete a file in JDK 7?

In this example you’ll learn how to create and delete a file. Using the new Files class helper from the JDK 7 you can create a file using the Files.createFile(Path) method. To delete a file you can use the Files.delete(Path) method.

Before create a file and delete a file we can check to see if the file exists or not using the Files.exists(Path) method. In the code snippet below we’ll create a file when the file is not exist. And we’ll delete the file if the file exists.

package org.kodejava.io;

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

public class CreateDeleteFile {
    public static void main(String[] args) {
        try {
            // Create a config.cfg file under D:Temp directory.
            Path path = Paths.get("F:/Temp/config.cfg");
            if (!Files.exists(path)) {
                Files.createFile(path);
            }

            // Delete the path.cfg file specified by the Path.
            if (Files.exists(path)) {
                Files.delete(path);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

How to recursively list all text files in a directory?

In this example you’ll learn how to use the Files.walkFileTree() to walk through file tree. This method requires two parameters. The first parameter is the starting file, in this example we’ll start from drive F:/Temp. And the second parameter is the file visitor to invoke for each file. Here we’ll create a file visitor call FindTextFilesVisitor which extend the java.nio.file.SimpleFileVisitor.

To get all the text files (files end with .txt) we override the visitFile() defined by the SimpleFileVisitor. In this method we check if the file ends with .txt extension and print the file name when the extension matches. And we continue to walk the file tree by returning FileVisitResult.CONTINUE.

package org.kodejava.io;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

public class WalkFileTree {
    public static void main(String[] args) {
        try {
            Path startDir = Paths.get("F:/Temp");
            Files.walkFileTree(startDir, new FindTextFilesVisitor());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * FindTextFilesVisitor.
     */
    static class FindTextFilesVisitor extends SimpleFileVisitor<Path> {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            if (file.toString().endsWith(".txt")) {
                System.out.println(file.getFileName());
            }
            return FileVisitResult.CONTINUE;
        }
    }
}

Instead of listing files, you can modify the code snippet above for instance use it to delete all the files that ends with .bak. Simply change the extension and replace the print-out statement with a file delete statement in the visitFile() method.