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