File Navigation and I/O ·
‹ Previous Next ›
⏱ 5 min read Modified: 2026-10-31

Java File Class: Working with Files and Directories

The line File file = new File("report.txt"); runs without errors, but if the file did not exist before, it still does not exist after: file.exists() returns false, file.length() returns 0, and no exception is thrown anywhere. A File object is just a path, not the file itself, and most of its methods report problems by returning false, 0 or null.

The File class (java.io.File) is an abstract representation of a file or directory path in the file system. Unlike most java.io classes, it does not work with streams and does not read file content: you use it to check whether a file exists, get its size, last-modified time and access rights (canRead(), canWrite()), create, rename and delete files and directories, list the contents of a directory and navigate the directory tree.

File class constructors

A File object is created with one of four constructors: from a full path, from a parent directory path plus a name, from a parent File plus a name, or from a URI. No constructor touches the disk or creates a file — it only stores the path.

Constructor Parameters Example
File(String pathname) Path to a file or directory (absolute or relative) new File("src/io/file.txt")
File(String parent, String child) Path to the parent directory and the name of a file (or subdirectory) inside it new File("src/io", "file.txt")
File(File parent, String child) A File for the parent directory and the name of a file inside it new File(dir, "file.txt")
File(URI uri) A URI with the file: scheme that describes the file new File(URI.create("file:///C:/data/file.txt"))

You can write the directory separator as / — Java accepts it on Windows too and converts it to the system separator (\) when the path is printed. The system separator is available as the constant File.separator, but the two-argument constructors are the most convenient: they insert the right separator for you.

Where a relative path starts from

A relative path ("src/io/file.txt") is resolved against the JVM working directory — System.getProperty("user.dir") — not against the folder that contains the class. In IntelliJ IDEA that is the project root by default; with java -jar it is the directory the command was run from. That is why a program that “sees” a file in the IDE may not find it after packaging.

Java File methods

The methods of the Java File class fall into two groups: information methods (name, path, size, existence, type, permissions) and file system operations (create, rename, delete, list). Almost none of the operations throw exceptions — they return false instead, so you have to check the result.

File information

Method Returns If the file does not exist
getName() Name of the file or directory — the last element of the path The name from the path
getPath() The path as passed to the constructor (with system separators) The path from the constructor
getAbsolutePath() Absolute path starting from the file system root Built anyway
getParent() Parent directory path as a String; getParentFile() returns it as a File null if the path has no parent (new File("a.txt"))
exists() true if the file or directory exists false
isFile() true if it is a regular file, not a directory false
isDirectory() true if it is a directory false
isAbsolute() true if the path is absolute Depends only on the path
canRead(), canWrite(), canExecute() Whether the file can be read, written, executed false
length() File size in bytes (long) 0; for a directory the value is unspecified
lastModified() Last-modified time in milliseconds since January 1, 1970 (UTC) 0
isHidden() true if the file is hidden false

Operations on files and directories

Method What it does On failure
createNewFile() Creates an empty file if it does not exist yet false if the file already exists; IOException if the parent directory is missing
mkdir() Creates a single directory false if the directory already exists or its parent is missing
mkdirs() Creates the directory and all missing parent directories false if the directory already exists or could not be created
renameTo(File dest) Renames or moves the file; the parameter is a File with the new path false (for example, the target already exists or is on another drive — OS-dependent)
delete() Deletes a file or an empty directory false, including for a non-empty directory
list() Array of names (String[]) of files and subdirectories null if this is not a directory or an I/O error occurs
listFiles() Array of File[] objects; overloads take a FileFilter or FilenameFilter null, same as list()
toPath() Converts the File to a java.nio.file.Path (Java 7+) InvalidPathException for an invalid path

The full list of methods is in the official java.io.File documentation (Java 21).

Example: getting file information

To get information about a file in Java, create a File object and call its information methods: getName(), getAbsolutePath(), exists(), length(), lastModified(). To check if a file exists in Java, call exists() — and, if you need a regular file rather than a directory, isFile(). The program below prints all the main properties of a file.

Example 1. Getting file information

import java.io.File;
import java.time.Instant;

public class FileExample {
    public static void main(String[] args) {
        File file = new File("src/io/file.txt");

        System.out.println("Name: " + file.getName());
        System.out.println("Path: " + file.getPath());
        System.out.println("Absolute path: " + file.getAbsolutePath());
        System.out.println("Parent: " + file.getParent());
        System.out.println(file.exists() ? "Exists." : "Does not exist.");
        System.out.println(file.canWrite() ? "Writable." : "Not writable.");
        System.out.println(file.canRead() ? "Readable." : "Not readable.");
        System.out.println(file.isDirectory() ? "Directory." : "Not a directory.");
        System.out.println(file.isFile() ? "Regular file." : "Not a regular file.");
        System.out.println(file.isAbsolute() ? "Absolute path." : "Relative path.");
        System.out.println("Last modified (ms): " + file.lastModified());
        System.out.println("Last modified: " + Instant.ofEpochMilli(file.lastModified()));
        System.out.println("Size: " + file.length() + " bytes.");
    }
}

Output (Windows, project in C:\projects\demo, a 26-byte file; your modification time will differ):

Name: file.txt
Path: src\io\file.txt
Absolute path: C:\projects\demo\src\io\file.txt
Parent: src\io
Exists.
Writable.
Readable.
Not a directory.
Regular file.
Relative path.
Last modified (ms): 1793404800000
Last modified: 2026-10-31T00:00:00Z
Size: 26 bytes.

Replace the path with "missing.txt" (no such file) and the program still runs without exceptions, but every value becomes “empty”:

Name: missing.txt
Path: missing.txt
Absolute path: C:\projects\demo\missing.txt
Parent: null
Does not exist.
Not writable.
Not readable.
Not a directory.
Not a regular file.
Relative path.
Last modified (ms): 0
Last modified: 1970-01-01T00:00:00Z
Size: 0 bytes.

So length() == 0 does not mean the file is empty: check exists() first.

Working with directories: mkdir vs mkdirs, list, listFiles

A directory in Java is also a File object, one for which isDirectory() returns true. You create it with mkdir() (one level) or mkdirs() (together with any missing parent directories), and read its contents with list() (names) or listFiles() (File objects).

The difference between mkdir() and mkdirs() shows up when the parent directories do not exist yet:

File dir = new File("out/reports/2026");
System.out.println(dir.mkdir());   // false - out/reports does not exist
System.out.println(dir.mkdirs());  // true  - creates out, out/reports and out/reports/2026
System.out.println(dir.mkdirs());  // false - the directory already exists

mkdirs() creates the directory itself and every missing parent directory. A second call returns false, so to check that “the directory is there” rely on dir.isDirectory(), not on the result of mkdirs().

Example 2. Listing the contents of a directory

list() returns only names, so you would have to rebuild the path for each one. listFiles() returns File objects right away, and you can call isDirectory() on them:

import java.io.File;
import java.util.Arrays;

public class DirList {
    public static void main(String[] args) {
        File catalog = new File("src");

        File[] files = catalog.listFiles();
        if (files == null) {
            System.out.println(catalog.getName() + " is not a directory or cannot be read");
            return;
        }
        Arrays.sort(files); // the order of listFiles() is not guaranteed
        System.out.println("Directory " + catalog.getName());
        for (File file : files) {
            String type = file.isDirectory() ? "directory" : "file";
            System.out.println("  " + file.getName() + " - " + type);
        }
    }
}

Output (the src directory contains the subdirectory io and the file Main.java):

Directory src
  io - directory
  Main.java - file

If src does not exist, listFiles() returns null and the program prints src is not a directory or cannot be read. Without the null check, the for loop would fail with a NullPointerException.

To pick only the files you need, pass a filter to listFiles() — for example, a FileFilter lambda:

File[] javaFiles = new File("src").listFiles(f -> f.isFile() && f.getName().endsWith(".java"));
// for the directory above: an array with one element, src\Main.java

Create, rename and delete a file in Java

To create an empty file in Java with the File class, call createNewFile(); to rename or move it, renameTo(File dest); to delete it, delete(). All three return a boolean. Only createNewFile() throws the checked IOException, so the calling method must catch it or declare it in throws (see checked and unchecked exceptions).

Example 3. What does this code print?

import java.io.File;
import java.io.IOException;

public class FileOperations {
    public static void main(String[] args) throws IOException {
        File file = new File("temp.txt");
        System.out.println(file.createNewFile());     // 1
        System.out.println(file.createNewFile());     // 2

        File renamed = new File("temp-old.txt");
        System.out.println(file.renameTo(renamed));   // 3
        System.out.println(file.exists());            // 4
        System.out.println(renamed.exists());         // 5
        System.out.println(renamed.delete());         // 6

        File out = new File("out");                   // directory from the mkdirs example, contains out/reports
        System.out.println(out.delete());             // 7
    }
}

Output (temp.txt and temp-old.txt do not exist before the run):

true
false
true
false
true
true
false

Line 2 prints false: the file already exists, and a second createNewFile() does not overwrite it. Line 4 prints false even though the rename succeeded: the file object still points to temp.txt, which is gone. Line 7 prints false: delete() does not remove a non-empty directory — you have to delete its contents first.

A File object is immutable

The path inside a File is set once in the constructor and never changes. After renameTo(), keep working with the object you passed as the parameter (renamed), not with the original one.

File itself does not read or write file content — for that you pass the File object to a stream constructor: new FileInputStream(file) for bytes, new FileReader(file) for text. How streams work is covered in Java I/O Streams.

File vs Path and Files: which to use

Java 7 added the java.nio.file package with the Path interface (a path) and the Files utility class (operations). They solve the same tasks as java.io.File, but on failure they throw an exception that names the cause instead of returning false, and they can also copy files and read their content. New code usually uses Path and Files; File stays in legacy code and in APIs that take a File parameter.

Task java.io.File java.nio.file.Files
Check existence file.exists() Files.exists(path)
Create a file createNewFile() → false if it exists Files.createFile(path) → FileAlreadyExistsException
Delete delete() → false with no reason Files.delete(path) → NoSuchFileException or DirectoryNotEmptyException
Rename, move renameTo(dest) → false Files.move(src, dest) → exception with the cause
Create directories mkdirs() Files.createDirectories(path)
List a directory listFiles() → File[] or null Files.list(dir) → Stream<Path>
Copy a file No method Files.copy(src, dest)
Read the whole text No method, streams needed Files.readString(path) (Java 11)

Switching between the two APIs takes one call: file.toPath() and path.toFile(). The Stream<Path> returned by Files.list() keeps the directory open and must be closed — the usual way is try-with-resources.

Common gotchas with the File class

Most bugs with the File class come from two sources: it silently returns false or null instead of throwing an exception, and paths depend on the operating system and the working directory. The table shows what happens in each case and how to fix it.

Mistake What happens Fix
for (File f : dir.listFiles()) without a check NullPointerException if the directory is missing or not readable Store the result in a variable and check it for null
Ignoring the result of delete(), mkdir(), renameTo() The operation failed, but the program carries on as if all is well Check the boolean, or use Files.delete()/Files.move(), which throw an exception
Hard-coded path "C:\\data\\file.txt" Linux and macOS have no such path, and a backslash there is an ordinary file name character Read the path from configuration or build it with new File(parent, child)
Expecting length() to return a directory size For a directory the value is unspecified (typically 0 on Windows, 4096 on Linux) Sum length() of the files recursively
try (File f = new File("a.txt")) Compile error: File does not implement AutoCloseable There is nothing to close: File does not open the file. Close the streams created from it

Frequently asked questions

Is the File class deprecated in Java?

No. java.io.File is not marked @Deprecated and is supported in every Java version. For new code, though, Path and Files from java.nio.file are recommended: they give meaningful exceptions and more operations. A task-by-task comparison is in File vs Path and Files.

What is the difference between getAbsolutePath() and getCanonicalPath()?

getAbsolutePath() simply prepends the working directory to a relative path: new File("src/../pom.xml") gives C:\projects\demo\src\..\pom.xml. getCanonicalPath() queries the file system, removes . and .., resolves symbolic links and returns C:\projects\demo\pom.xml; it can throw IOException. Use the canonical path to check whether two paths point to the same file.

What is the difference between createNewFile() and new FileOutputStream(file)?

Both create the file if it does not exist. But if the file already exists, createNewFile() returns false and leaves it alone, while new FileOutputStream(file) silently truncates it to 0 bytes — the content is lost. To append to the end, use new FileOutputStream(file, true).

How do I get a file extension with File?

The File class has no such method. Take the extension from the name: String name = file.getName(); int dot = name.lastIndexOf('.'); String ext = dot > 0 ? name.substring(dot + 1) : "";. The dot > 0 condition skips hidden files like .gitignore, where the dot comes first.

How do I delete a directory with all its contents?

delete() removes only an empty directory, so delete the nested files and subdirectories recursively first: walk through listFiles(), call the same method for every subdirectory, then delete the directory itself. Neither File nor Files has a ready-made “delete everything” method.

Comments

Please log in or register to have a possibility to add comment.