Как указать путь к файлу в java
Чтобы указать путь к файлу в Java , можно использовать класс java.io.File . Существует несколько способов задания пути:
File file = new File("/path/to/file.txt"); // Здесь /path/to/file.txt - абсолютный путь к файлу.
Относительный путь от текущего каталога:
File file = new File("file.txt"); // Здесь file.txt - файл, расположенный в текущем каталоге.
Относительный путь от корня проекта:
File file = new File("src/main/resources/file.txt");
Знакомство с файлами
Если вы хотите написать программу, которая делает что-то с файлами на диске, это у вас очень легко получится. В Java очень много классов, которые помогают вам работать как с самими файлами, так и с их содержимым.
В ранних версиях Java для работы с файлами использовались классы типа File и FileInputStream . Но теперь класс File считается устаревшим, и использовать его не рекомендуется. Вы, конечно, можете еще встретить его в коде, параметрах методов или конструкторах классов.
Мы будем начинать изучение работы с файлами сразу с класса Path . Path — это класс, который пришел на смену File . Работа с ним безопаснее и эффективнее.
Класс Path
Технически Path — это не класс, а интерфейс. Так сделано для того, чтобы можно было под каждую операционную (и файловую) систему писать свой класс-наследник Path .
У Windows свои стандарты написания пути файлов, у Linux — свои. А ведь в мире еще много операционных систем, и у каждой — свои стандарты.
Поэтому везде в методах для работы с файлами указан интерфейс Path , а реально работа идет с его классами-наследниками: WindowsPath , UnixPath , .
Создание объекта Path
Чтобы создать объект Path (на самом деле это будет объект класса-наследника — WindowsPath ), нужно воспользоваться командой вида:
Path имя = Path.of(путь);
Где имя — это имя переменной типа Path . путь — это путь к файлу (или директории) вместе с именем файла (или директории). А of — статический метод класса Path .
Метод of() используется для того, чтобы создать объекты типа WindowsPath если программа запускается под Windows, а если программа запускается под Linux — объекты UnixPath . Вы не можете создать объект типа Path с помощью кода вида new Path() .
Path file = Path.of("c:\\projects\\note.txt");
Path directory = Path.of("c:\\projects\\");
Файл (или директория) не обязаны существовать, чтобы мог существовать валидный объект типа Path . Может вы только хотите создать файл. Объект типа Path — это как продвинутая версия типа String — он не привязан к конкретному файлу на диске: он просто хранит некий путь на диске и все.
2. Методы типа Path
У интерфейса Path есть довольно много интересных методов. Самые интересные представлены в таблице ниже.
Path getParent()
Path getFileName()
Path getRoot()
boolean isAbsolute()
Path toAbsolutePath()
Path normalize()
Path resolve(Path other)
Path relativize(Path other)
boolean startsWith(Path other)
boolean endsWith(Path other)
int getNameCount()
Path getName(int index)
Path subpath(int beginIndex, int endIndex)
File toFile()
URI toUri()
Ниже идет краткое описание существующих методов.
3. Разделение пути на части
Метод getParent() возвращает путь, который указывает на родительскую директорию для текущего пути. Независимо от того, был этот путь директорией или файлом:
String str = "c:\\windows\\projects\\note.txt"; Path path = Path.of(str).getParent();
"c:\\windows\\projects\\"
String str = "c:\\windows\\projects\\"; Path path = Path.of(str).getParent();
"c:\\windows\\"
String str = "c:\\"; Path path = Path.of(str).getParent();
null
Метод getFileName() возвращает одно имя файла (или директории) — то, что идет после последнего разделителя:
String str = "c:\\windows\\projects\\note.txt"; Path path = Path.of(str).getFileName();
"note.txt"
String str = "c:\\windows\\projects\\"; Path path = Path.of(str).getFileName();
"projects"
String str = "c:\\"; Path path = Path.of(str).getFileName();
null
Метод getRoot() возвращает путь к корневой директории:
String str = "c:\\windows\\projects\\"; Path path = Path.of(str).getRoot();
4. Абсолютный и относительный пути
Пути бывают двух типов: абсолютные и относительные. Абсолютный путь начинается с корневой директории. Для Windows это может быть папка c:\ , для Linux — директория /
Относительный путь считается относительно какой-то директории. Т.е. это как бы конец пути, но только без начала. Относительный путь можно превратить в абсолютный и наоборот
Метод boolean isAbsolute()
Метод проверяет, является ли текущий путь абсолютным
String str = "c:\\windows\\projects\\note.txt"; boolean abs = Path.of(str).isAbsolute();
true
String str = "src\\com\\javarush\\Main.java"; boolean abs = Path.of(str).isAbsolute();
false
Метод Path toAbsolutePath()
Превращает путь в абсолютный, если нужно — добавляет к нему текущую рабочую директорию:
String str = "c:\\windows\\projects\\note.txt"; Path path = Path.of(str).toAbsolutePath();
"c:\\windows\\projects\\note.txt"
String str = "src\\com\\javarush\\Main.java"; Path path = Path.of(str).toAbsolutePath();
"d:\\work\\src\\com\\javarush\\Main.java"
Метод Path normalize()
В пути вместо имени директории можно писать «..», и это будет означать вернуться на одну директорию назад. Нормализация устраняет эти вещи. Примеры:
String str = "c:\\windows\\..\\projects\\note.txt"; Path path = Path.of(str).normalize();
"c:\\projects\\note.txt"
String str = "src\\com\\javarush\\..\\Main.java"; Path path = Path.of(str).normalize();
"src\\com\\Main.java"
Метод Path relativize(Path other)
Метод relativize() позволяет вычислить «разницу путей»: один путь относительно другого
Path path1 = Path.of("c:\\windows\\projects\\note.txt"); Path path2 = Path.of("c:\\windows\\"); Path result = path2.relativize(path1);
"projects\\note.txt"
Path path1 = Path.of("c:\\windows\\projects\\note.txt"); Path path2 = Path.of("c:\\windows\\"); Path result = path1.relativize(path2);
Path path1 = Path.of("c:\\aaa\\bbb\\1.txt"); Path path2 = Path.of("d:\\zzz\\y.jpg"); Path result = path1.relativize(path2);
Ошибка IllegalArgumentException: два пути имеют разный "корень" (разные диски)
Метод Path resolve(Path other)
Метод resolve() выполняет операцию, обратную relativize() : из абсолютного и относительного пути он строит новый абсолютный путь.
Path path1 = Path.of("projects\\note.txt"); Path path2 = Path.of("c:\\windows\\"); Path result = path1.resolve(path2);
"c:\\windows"
Path path1 = Path.of("projects\\note.txt"); Path path2 = Path.of("c:\\windows\\"); Path result = path2.resolve(path1);
"c:\\windows\\projects\\note.txt"
Метод toFile()
Метод возвращает устаревший объект File , который хранит тот же путь к файлу, что и объект Path .
Метод toURI()
Метод преобразует путь к стандарту URI , возвращает объект, который содержит путь к файлу:
c:\windows\projects\note.txt
file:///c:/windows/projects/note.txt
Как указать относительный путь к файлу в java
Класс File, определенный в пакете java.io, не работает напрямую с потоками. Его задачей является управление информацией о файлах и каталогах. Хотя на уровне операционной системы файлы и каталоги отличаются, но в Java они описываются одним классом File.
В зависимости от того, что должен представлять объект File — файл или каталог, мы можем использовать один из конструкторов для создания объекта:
File(String путь_к_каталогу) File(String путь_к_каталогу, String имя_файла) File(File каталог, String имя_файла)
// создаем объект File для каталога File dir1 = new File("C://SomeDir"); // создаем объекты для файлов, которые находятся в каталоге File file1 = new File("C://SomeDir", "Hello.txt"); File file2 = new File(dir1, "Hello2.txt");
Класс File имеет ряд методов, которые позволяют управлять файлами и каталогами. Рассмотрим некоторые из них:
- boolean createNewFile() : создает новый файл по пути, который передан в конструктор. В случае удачного создания возвращает true, иначе false
- boolean delete() : удаляет каталог или файл по пути, который передан в конструктор. При удачном удалении возвращает true.
- boolean exists() : проверяет, существует ли по указанному в конструкторе пути файл или каталог. И если файл или каталог существует, то возвращает true, иначе возвращает false
- String getAbsolutePath() : возвращает абсолютный путь для пути, переданного в конструктор объекта
- String getName() : возвращает краткое имя файла или каталога
- String getParent() : возвращает имя родительского каталога
- boolean isDirectory() : возвращает значение true, если по указанному пути располагается каталог
- boolean isFile() : возвращает значение true, если по указанному пути находится файл
- boolean isHidden() : возвращает значение true, если каталог или файл являются скрытыми
- long length() : возвращает размер файла в байтах
- long lastModified() : возвращает время последнего изменения файла или каталога. Значение представляет количество миллисекунд, прошедших с начала эпохи Unix
- String[] list() : возвращает массив файлов и подкаталогов, которые находятся в определенном каталоге
- File[] listFiles() : возвращает массив файлов и подкаталогов, которые находятся в определенном каталоге
- boolean mkdir() : создает новый каталог и при удачном создании возвращает значение true
- boolean renameTo(File dest) : переименовывает файл или каталог
Работа с каталогами
Если объект File представляет каталог, то его метод isDirectory() возвращает true . И поэтому мы можем получить его содержимое — вложенные подкаталоги и файлы с помощью методов list() и listFiles() . Получим все подкаталоги и файлы в определенном каталоге:
import java.io.File; public class Program < public static void main(String[] args) < // определяем объект для каталога File dir = new File("C://SomeDir"); // если объект представляет каталог if(dir.isDirectory()) < // получаем все вложенные объекты в каталоге for(File item : dir.listFiles())< if(item.isDirectory())< System.out.println(item.getName() + " \t folder"); >else < System.out.println(item.getName() + "\t file"); >> > > >
Теперь выполним еще ряд операций с каталогами, как удаление, переименование и создание:
import java.io.File; public class Program < public static void main(String[] args) < // определяем объект для каталога File dir = new File("C://SomeDir//NewDir"); boolean created = dir.mkdir(); if(created) System.out.println("Folder has been created"); // переименуем каталог File newDir = new File("C://SomeDir//NewDirRenamed"); dir.renameTo(newDir); // удалим каталог boolean deleted = newDir.delete(); if(deleted) System.out.println("Folder has been deleted"); >>
Работа с файлами
Работа с файлами аналогична работе с каталога. Например, получим данные по одному из файлов и создадим еще один файл:
import java.io.File; import java.io.IOException; public class Program < public static void main(String[] args) < // определяем объект для каталога File myFile = new File("C://SomeDir//notes.txt"); System.out.println("File name: " + myFile.getName()); System.out.println("Parent folder: " + myFile.getParent()); if(myFile.exists()) System.out.println("File exists"); else System.out.println("File not found"); System.out.println("File size: " + myFile.length()); if(myFile.canRead()) System.out.println("File can be read"); else System.out.println("File can not be read"); if(myFile.canWrite()) System.out.println("File can be written"); else System.out.println("File can not be written"); // создадим новый файл File newFile = new File("C://SomeDir//MyFile"); try < boolean created = newFile.createNewFile(); if(created) System.out.println("File has been created"); >catch(IOException ex) < System.out.println(ex.getMessage()); >> >
При создании нового файла метод createNewFile() в случае неудачи выбрасывает исключение IOException , поэтому нам надо его отлавливать, например, в блоке try. catch, как делается в примере выше.
Как указать относительный путь к файлу в java
На этом шаге мы рассмотрим особенности открытия файла, определения текущего каталога .
Очень часто нужно сохранить какие-либо данные. Для этого существуют два способа: запись в файл и сохранение в базу данных . Первый способ используется при сохранении информации небольшого объема. Если объем велик, то лучше (и удобнее) воспользоваться базой данных.
Открытие файла
Прежде чем работать с файлом, необходимо создать объект файла с помощью функции open () . Функция имеет следующий формат:
open(Путь к файлу>[, mode = 'r'] [, buffering=-1] [, encoding=None] [, errors=None][, newline=None][, closefd=True])
В первом параметре указывается путь к файлу. Путь может быть абсолютным или относительным. При указании абсолютного пути в Windows следует учитывать, что в Python слеш является специальным символом. По этой причине слеш необходимо удваивать или вместо обычных строк использовать неформатированные строки. Пример:
>>> "C:\\temp\\new\\file.txt" # Правильно 'C:\\temp\\new\\file.txt' >>> r"C:\temp\new\file.txt" # Правильно 'C:\\temp\\new\\file.txt' >>> "C:\temp\new\file.txt" # Неправильно. 'C:\temp\new\x0cile.txt'
Обратите внимание на последний пример. В этом пути из-за того, что слеши не удвоены, возникло присутствие сразу трех специальных символов: \t , \n и \f (отображается как \x0c ). После преобразования этих специальных символов путь будет выглядеть следующим образом: . , . .
С:Табуляция>empПеревод строки>ewПеревод формата>ile.txt
Если такую строку передать в функцию open () , то это приведет к исключению OSError :
>>> open("C:\temp\new\file.txt") Traceback (most recent call last): File "", line 1, in open("C:\temp\new\file.txt") OSError: [Errno 22] Invalid argument: 'C:\temp\new\x0cile.txt'
если открываемый файл находится в текущем рабочем каталоге, то можно указать только название файла. Пример:
>>> import os.path # Подключаем модуль >>> # Файл в текущем рабочем каталоге (C:\Python34\) >>> os.path.abspath(r"file.txt") 'C:\\Python34\\file.txt'
>>> # Открываемый файл в C:\Python34\folder1\ >>> os.path.abspath (r"folder1/file.txt") 'C:\\Python34\\folder1\\file.txt' >>> # Открываемый файл в C:\Python34\folder1\folder2\ >>> os.path.abspath(r"folder1/folder2/file.txt") 'C:\\Python34\\folder1\\folder2\\file.txt'
>>> # Открываемый файл в С:\ >>> os.path.abspath (r"../file.txt") 'C:\\file.txt'
>>> # Открываемый файл в C:\book\folder1\ >>> os.path.abspath (r"/book/folder1/file.txt") 'C:\\book\\folder1\\file.txt' >>> # Открываемый файл в C:\book\folder1\folder2\ >>> os.path.abspath (r"/book/folder1/folder2/file.txt") 'C:\\book\\folder1\\folder2\\file.txt'
Как можно видеть, в абсолютном и относительном путях можно указать как прямые, так и обратные слеши. Все они будут автоматически преобразованы с учетом значения атрибута sep из модуля os.path . Значение этого атрибута зависит от используемой операционной системы. Выведем значение атрибута sep в операционной системе Windows :
>>> os.path.sep '\\' >>> os.path.abspath (r"С:/book/folder1/file.txt") 'С:\\book\\folder1\\file.txt'
При использовании относительного пути необходимо учитывать местоположение текущего рабочего каталога, т. к. рабочий каталог не всегда совпадает с каталогом, в котором находится исполняемый файл. Если файл запускается с помощью двойного щелчка на его значке, то каталоги будут совпадать. Если же файл запускается из командной строки, то текущим рабочим каталогом будет каталог, из которого запускается файл.
Рассмотрим все это на примере, для чего в каталоге C:\book создадим следующую структуру файлов:
С:\book\ test.py folder1\ __init__.py module1.py
Содержимое файла C:\book\test.py :
# -*- coding: utf-8 -*- import os, sys print("%-25s%s" % ("Файл:", os.path.abspath(__file__))) print("%-25s%s" % ("Текущий рабочий каталог:", os.getcwd())) print("%-25s%s" % ("Каталог для импорта:", sys.path[0])) print("%-25s%s" % ("Путь к файлу:", os.path.abspath("file.txt"))) print("-" * 40) import folder1.module1 as m m.get_cwd()
Файл C:\book\folder1\__init__.py создаем пустым. Как вы уже знаете, этот файл указывает интерпретатору Python , что данный каталог является пакетом с модулями.
Содержимое файла C:\book\folder1\module1.py :
# -*- coding: utf-8 -*- import os, sys def get_cwd(): print("%-25s%s" % ("Файл:", os.path.abspath(__file__))) print("%-25s%s" % ("Текущий рабочий каталог:", os.getcwd())) print("%-25s%s" % ("Каталог для импорта:", sys.path[0])) print("%-25s%s" % ("Путь к файлу:", os.path.abspath("file.txt")))
Архив со структурой каталогов и файлами можно взять здесь.
Запускаем командную строку, переходим в каталог C:\book и запускаем файл test.py :
Рис.1. Результат выполнения файла test.py
В этом примере текущий рабочий каталог совпадает с каталогом, в котором расположен файл test.py . Однако обратите внимание на текущий рабочий каталог внутри модуля module1.py . Если внутри этого модуля в функции open() указать название файла без пути, то поиск файла будет произведен в каталоге C:\book , а не C:\book\folder1 .
Теперь перейдем в корень диска С: и опять запустим файл test.py :
Рис.2. Результат выполнения файла test.py
В этом случае текущий рабочий каталог не совпадает с каталогом, в котором расположен файл test.py . Если внутри файлов test.py и module1.py в функции open() указать название файла без пути, то поиск файла будет производиться в корне диска С: , а не в каталогах с этими файлами.
Чтобы поиск файла всегда производился в каталоге с исполняемым файлом, необходимо этот каталог сделать текущим с помощью функции chdir() из модуля os . Для примера изменим содержимое файла test.py :
# -*- coding: utf-8 -*- import os, sys # Делаем каталог с исполняемым файлом текущим os.chdir (os.path.dirname(os.path.abspath(__file__))) print("%-25s%s" % ("Файл:", __file__)) print("%-25s%s" % ("Текущий рабочий каталог:", os.getcwd())) print("%-25s%s" % ("Каталог для импорта:", sys.path[0])) print("%-25s%s" % ("Путь к файлу:", os.path.abspath("file.txt")))
Архив с этим файлом можно взять здесь.
Обратите внимание на четвертую строку. С помощью атрибута __file__ мы получаем путь к исполняемому файлу вместе с названием файла. Атрибут __file__ не всегда содержит полный путь к файлу. Например, если запуск осуществляется следующим образом:
С:\book>C:\Python34\python test.py,
то атрибут будет содержать только название файла без пути. Чтобы всегда получать полный путь к файлу, следует передать значение атрибута в функцию abspath() из модуля os.path . Далее мы извлекаем путь (без названия файла) с помощью функции dirname() и передаем его функции chdir() . Теперь, если в функции open() указать название файла без пути, то поиск будет производиться в каталоге с этим файлом. Запустим файл test.py с помощью командной строки:
Рис.3. Результат выполнения файла test.py
Функции, предназначенные для работы с каталогами, мы еще рассмотрим подробно в следующих шагах. Сейчас же важно запомнить, что текущим рабочим каталогом будет каталог, из которого запускается файл, а не каталог, в котором расположен исполняемый файл. Кроме того, пути поиска файлов не имеют никакого отношения к путям поиска модулей.
На следующем шаге мы закончим рассмотрение функции open() .
