Оригинал: Miss Sister Taste (идентификатор публичной учетной записи WeChat: xjjdog), добро пожаловать, пожалуйста, сохраните источник для перепечатки.
Любой, кто читал файлы из пути к классам, знает, что очень громоздко писать некоторые методы для чтения потоков. Недавно использовал IDEA для игры.
При использовании этого символа интересна одна строка кода: она предоставляет метод прямого чтения байтов байтов.
byte[] bytes = Test
.class
.getResourceAsStream("/test.txt")
.readAllBytes();
Это действительно здорово — никогда больше не писать какой-то уродливый код потока, который легко забыть закрыть.
К сожалению, подсказки кода попали в самую точку. Для этого требуется Java версии 9+. Это как пациент, которому осталось жить один год и который видит спасительное лекарство, которое появится только через два года.
Не говорите чепухи, мы не можем использовать эти функции, разве мы не можем использовать Java7+ (некоторые бедные дети действительно не могут его использовать)? Сказав это, JAVA7+ расширил NIO, в основном сделав множество улучшений в части операций с файлами. Это выражается в разделении, инкапсуляции и улучшении файловых операций, и, наконец, формируются три основных класса Path (пути), Files и FileSystem (файловые системы).
Мы ласково называем его NIO2.
Среди них Paths и Files предоставляют большое количество удобных статических методов работы; NIO2 также предоставляет расширенные API, такие как операции с правами доступа (атрибутами) к файлам, программные соединения и поиск файлов, что делает NIO2 более полным интерфейсом работы с файловой системой.
Новички, возможно, сталкивались с этим в начале, но для некоторых из нас, старых программистов, внезапное наблюдение за этими вещами равносильно открытию нового континента. Так что эта статья предназначена для новичков, которые еще не знакомы с этими операциями, а также для старых Java-программистов на поздней стадии ленивого рака.
1. Путь
Файловые системы организованы по древовидной или иерархической структуре.Любой узел может быть каталогом или файлом, который называется Path в NIO2, который имеет много общего с исходным File, но Path имеет более репрезентативную семантику.
1.1, основные атрибуты
Следующий код показывает его основные свойства.
Path path = Paths.get("/data/logs/web.log");
//属性
//获取路径中的文件名或者最后一个节点元素
System.out.printf("FileName:%s%n", path.getFileName());
//路径节点元素的格式
System.out.printf("NameCount:%s%n", path.getNameCount());
//遍历路径节点方法1
Iterator<Path> names = path.iterator();
int i = 0;
while (names.hasNext()) {
Path name = names.next();
System.out.printf("Name %s:%s%n",i,name.toString());
i++;
}
//方法2
for(int j = 0; j < path.getNameCount(); j++) {
System.out.printf("Name %s:%s%n",j,path.getName(j));
}
//父路径
System.out.printf("Parent:%s%n",path.getParent());
//跟路径,比如"/"、"C:";如果是相对路径,则返回null。
System.out.printf("Root:%s%n",path.getRoot());
//子路径,结果中不包含root,前开后闭
System.out.printf("Subpath[0,2]:%s%n",path.subpath(0,2));
результат:
FileName:web.log
NameCount:3
Name 0:data
Name 1:logs
Name 2:web.log
Name 0:data
Name 1:logs
Name 2:web.log
Parent:/data/logs
Root:/
Subpath[0,2]:data/logs
1.2, преобразование пути
1) Например, «/data/logs/./web.log» и «/data/logs/../db» содержат «избыточные» пути, иногда нам нужно преобразовать их в обычные операторы пути, а затем использовать «Путь .normalize()", очень освежающий и чистый.
Path path = Paths.get("/data/logs/../web.log");
//输出结果:/data/web.log
System.out.printf("%s%n",path.normalize());
2) Если к файлу нужно получить доступ внешними ресурсами (ресурсом), вы можете преобразовать его через Path.toUri(), файл или каталог, соответствующий пути, может не существовать, этот метод не будет проверять исключение:
Path path = Paths.get("/data/logs/web.log");
//表示本地文件的uri,输出结果:file:///data/logs/web.log
System.out.printf("%s%n",path.toUri());
3) toAbsolutePath(): если путь является относительным путем, он будет преобразован в абсолютный путь.Для программ JAVA начальным путем является путь к классам. Этот метод не определяет, существует ли файл на самом деле или есть ли у него разрешения.
4) Среди них toRealPath() является более важным методом, но он определяет, существует ли файл и права доступа, и должен перехватывать исключения. Сначала проверьте, существует ли файл и есть ли у него разрешение; если путь является относительным путем, он будет преобразован в абсолютный путь, такой же, как «3)»; если это файл «символической ссылки» (мягкая ссылка), будет получен его фактический целевой путь (если не указано NO_FOLLOW_LINKS); если путь содержит «избыточность», удалите ее, как и 1). Этот метод, который обычно используется для преобразования контрольной суммы по «пути, введенному пользователем», широко используется.
5) resolve(): путь объединяется, текущий путь объединяется с параметрами и добавляется.
6) relativize(): получить относительный путь, относительный путь между "/data" и "/data/logs/p1" равен "logs/p1", иначе "../../".
2. Файлы
Класс Files предоставляет большое количество статических методов для создания, копирования, переноса, удаления и доступа к файловым данным файлов (каталогов).
2.1 Обнаружение файлов или каталогов
Files.exists(Path) и notExists(Path) — это два метода, оба из которых фактически определяют, существует ли файл или каталог и есть ли у него права доступа. Примечание: !exist() и notExists() не совсем равны, у существования может быть три состояния: если он не существует или проверка безопасности не удалась, он вернет false, а если вернет true, это означает, что файл существует. и имеет разрешение. Тест notExists() аналогичен, и он вернет false для тех, кто не прошел проверку безопасности; когда exists и notExists вернут false одновременно, это означает, что файл не может быть проверен (то есть нет разрешения), поэтому обычно эти два метода необходимо использовать одновременно.
Чтобы определить, что файл (каталог) имеет права на чтение, запись и выполнение, вы можете использовать следующие методы:
Path path = Paths.get("data/logs/web.log");
boolean isRegularExecutableFile = Files.isRegularFile(path) &
Files.isReadable(path) & Files.isExecutable(path);
Иногда два разных пути указывают на один и тот же файл. Например, если путь является программной ссылкой, вы можете использовать Files.isSameFile(p1, p2) для его обнаружения. Конечно, вы можете получить цель с помощью комбинации Path + LinkOption фактический путь для сравнения.
2.2, удалить
И delete, и deleteIfExists могут удалять файлы. Первый вызовет исключение, если файл, который он пытается удалить, не существует. Если файл представляет собой программную ссылку, будет удален только файл подключения без удаления целевого файла.Если путь является каталогом, каталог должен быть пустым, иначе удаление не удастся (IOException). Перед операцией удаления, наконец, выполните некоторые рутинные проверки, например, существует ли файл (имеет ли он разрешения), не пуст ли каталог и т. д. Мы рассмотрим «рекурсивное удаление деревьев каталогов и файлов» позже.
2.3, копия файла (каталога)
Метод copy(Path,Path,CopyOption...) может копировать файлы, однако вам нужно обратить внимание на соответствующие параметры CopyOption.
При копировании файла программной ссылки целевой файл будет скопирован по умолчанию. Если вы хотите скопировать только файл программной ссылки вместо целевого содержимого, вы можете указать параметр NOFOLLOW_LINKS. Классом реализации CopyOption является StandardCopyOption, а CopyOption также расширяет LinkOption, то есть содержит параметр NOFOLLOW_LINKS. Ниже приведен список опций CopyOption:
1)REPLACE_EXISTING: Если целевой файл уже существует, он будет перезаписан напрямую; если целевой файл является программной ссылкой, будет перезаписан сам файл программной ссылки (а не целевой файл файла подключения); если каталог копируется, а целевой Если каталог не пуст, то будет выдано исключение (DirectoryNotEmptyException), а позже будет введено «рекурсивное копирование деревьев каталогов и файлов». Обычно этот параметр является обязательным. При копировании каталога целевой каталог будет создан автоматически.Если в исходном каталоге есть файл, файл не будет скопирован, будет создан только пустой целевой каталог. источник и цель, каталог или файл одновременно.
2)COPY_ATTRIBUTES: При копировании файлов также копируются атрибуты целевого файла (метаданные), поддержка атрибутов файла (FileAttribute) зависит от файловой системы (и платформы), но обычно копируется lastModifiedTime.
3)NOFOLLOW_LINKS: унаследовано от LinkOption, указывающее, что если файл является программной ссылкой, за ним не следует, то есть копируется только файл ссылки, а фактическое содержимое файла его цели не копируется.
4)ATOMIC_MOVE: поддерживается только операция перемещения, копирование не поддерживается.
Path source = Paths.get("/data/logs/web.log");
Path target = Paths.get("/data/logs/web.log.copy");
Files.copy(source,target,REPLACE_EXISTING,COPY_ATTRIBUTES,NOFOLLOW_LINKS);
2.4 Мобильный
move(Path,Path,CopyIOption), основной принцип тот же, что и при копировании. Обратите внимание, что в случае каталога можно также перемещать каталог, содержащий файлы (это может зависеть от платформы), и подкаталоги также перемещаются вместе, но целевой каталог должен быть пустым (DirectoryNotEmptyException). Основная семантика такая же, как у "mv -rf". Целевой каталог не нужно создавать заранее. После перемещения исходный каталог не будет существовать. Поддерживаются два варианта:
1)REPLACE_EXISTING: если целевой файл уже существует, он будет перезаписан; если целевой файл представляет собой программную ссылку, файл ссылки будет перезаписан, но его указание не изменится.
2)ATOMIC_MOVE: атомарная копия, для которой требуется поддержка файловой системы платформы (если этот параметр не поддерживается, будет выдано исключение), другие параметры будут игнорироваться при указании этого параметра; если файл не может быть атомарно скопирован (или заменен), AtomicMoveNotSupportedException быть брошенным.
2.5, откройте файл
Класс Files предоставляет несколько статических методов для прямого чтения и записи файлов. Ниже приведены несколько вариантов открытия файла (StandardOpenOptions):
1)WRITE: открыть файл для записи.
2)APPEND: добавить данные в конец файла с помощью опции WRITE или CREATE.
3)TRUNCATE_EXISTING: обрезать файл до нуля вместе с опцией WRITE. Например, если файл существует, очистите данные файла и перезапишите его.
4)CREATE_NEW: создает новый файл, выдает исключение, если файл уже существует.
5)CREATE: открыть файл напрямую, если он уже существует, в противном случае создать файл.
6)DELETE_ON_CLOSE: Удалить файл при закрытии файловой операции (метод закрытия или завершение работы JVM), этот параметр применяется к временным файлам (к временным файлам не должны одновременно обращаться другие процессы).
7)SPARSE: Создает «разреженный» файл вместе с CREATE_NEW для специальных файловых систем, таких как NTFS.Эти большие файлы допускают «пробелы» (дыры) для повышения производительности в некоторых случаях без использования дискового пространства.
8)SYNC: изменения содержимого файла (данных) или метаданных будут синхронизированы с базовым хранилищем.
9)DSYNC: изменения содержимого файла будут синхронизированы с базовым хранилищем.
Для некоторых небольших файлов (M-уровень) обычно мы хотим прочитать все сразу, вместо итеративного чтения традиционным способом.
//全部读取小文件中的数据
//Files.readAllBytes(Paths.get("/data/web.log"));
List<String> lines = Files.readAllLines(Paths.get("/data/web.log"),Charset.forName("utf-8"));
//将准备好的数据,直接全部写入文件。(打开、写入)
Files.write(Paths.get("/data/web-1.log"),lines,Charset.forName("utf-8"),
StandardOpenOption.APPEND,
StandardOpenOption.CREATE));
//传统操作
try (BufferedReader reader = Files.newBufferedReader(Paths.get("/data/web.log"))) {
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
System.out.println(line);
}
} catch (IOException e) {
//
}
//传统操作
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("/data/web.log"),Charset.forName("utf-8"),StandardOpenOption.APPEND,
StandardOpenOption.CREATE)) {
for(String line : lines) {
writer.write(line);
}
} catch (IOException e) {
//
}
Кроме того, Files также предоставляет операцию канала на основе буфера с возвращаемым типом SeekableByteChannel. Эта операция обычно подходит для чтения или записи, и данные могут быть распакованы на основе буферов. Другие функции аналогичны «файлам произвольного доступа». (Files.newByteChannel(), та же функция, что и File.open())
Path path = Paths.get("/data/web.log");
//创建一个普通文件,如果已存在则抛出异常,文件属性为默认。
Files.createFile(path);
//创建临时文件,临时文件的目录和前缀可以为null,后缀如果为null时默认使用".tmp";
Files.createTempFile(null,null,".tmp");
//创建一个软连接文件
Files.createSymbolicLink(Paths.get("/data/link.log"),Paths.get("/data/web.log"));
2.6, Управление метаданными
2.6.1, Базовые атрибуты файла
Базовый интерфейс BasicFileAttributes предоставляет некоторые базовые метаданные файла, такие как lastAccessTime, lastModifiedTime и т. д. Классы его реализации существуют в зависимости от платформы: DosFileAttributes, PosixFileAttribute, UnixFileAttribute и т. д. Атрибуты, поддерживаемые разными платформами, различаются. (В кроссплатформенных сценариях вам может понадобиться использовать FileStore, чтобы определить, поддерживает ли текущая файловая система соответствующий FileAttributeView)
Path path = Paths.get("/data/logs/web.log");
BasicFileAttributes attributes = Files.readAttributes(path,BasicFileAttributes.class);
System.out.println("regular file:" + attributes.isRegularFile());
System.out.println("directory:" + attributes.isDirectory());
System.out.println("symbolic link:" + attributes.isSymbolicLink());
System.out.println("modified time:" + attributes.lastModifiedTime().toMillis());
//修改系统更新属性
Files.setLastModifiedTime(path,FileTime.fromMillis(System.currentTimeMillis()));
//修改其他属性
Files.setAttribute(path,"dos:hidden",true);
Формат имени атрибута — «имя-представления:имя-атрибута», например «dos:hidden»; допустимые имена представлений в настоящее время включают «базовый», «posix», «unix», «владелец» (информация о владельце, разрешения ), список атрибутов должен соответствовать соответствующему классу атрибутов в соответствии с его собственной платформой, иначе это вызовет исключение настройки.
2.6.2, Атрибуты PosixFile
Path path = Paths.get("/data/logs/web.log");
PosixFileAttributes attributes = Files.readAttributes(path,PosixFileAttributes.class);
//用户组和权限
UserPrincipal userPrincipal = attributes.owner();
System.out.println(userPrincipal.toString());
GroupPrincipal groupPrincipal = attributes.group();
System.out.println(groupPrincipal.toString());
Set<PosixFilePermission> permissions = attributes.permissions();
//将权限转换为文件属性,用于创建新的文件,目前文件权限也是一种属性
FileAttribute<Set<PosixFilePermission>> fileAttribute = PosixFilePermissions.asFileAttribute(permissions);
Files.createFile(Paths.get("/data/test.log"),fileAttribute);
//修改文件权限,可以在permissions中增减权限列表,枚举
Files.setPosixFilePermissions(path,permissions);
Из строки разрешений создайте список разрешений
Set<PosixFilePermission> permissions = PosixFilePermissions.fromString("-rw-r--r--");
Files.setPosixFilePermissions(path, permissions);
Изменить владельца или группу файла (каталога):
Path path = Paths.get("/data/logs/web.log");
//首先找到系统中的其他用户,根据用户名
UserPrincipal userPrincipal = path.getFileSystem().getUserPrincipalLookupService().lookupPrincipalByName("userName");
Files.setOwner(path,userPrincipal);
//或者
Files.getFileAttributeView(path,FileOwnerAttributeView.class).setOwner(userPrincipal);
//修改group
GroupPrincipal groupPrincipal = path.getFileSystem().getUserPrincipalLookupService().lookupPrincipalByGroupName("groupName");
Files.getFileAttributeView(path,PosixFileAttributeView.class).setGroup(groupPrincipal);
2.6.3. UserDefinedFileAttributeView
Определяемые пользователем атрибуты файла (т. е. расширенные атрибуты файла) и длина значения атрибута в зависимости от того, поддерживает ли его базовая файловая система или платформа. В настоящее время основные платформы и файловые системы поддерживают расширенные атрибуты файлов, такие как FreeBSD (ZFS), Linux (ext3, ext4, ZFS), MacOS и т. д. По умолчанию эта операция включена, если она отключена, вы можете передать «sudo mount -o remount, user_xattr {путь монтирования вашей файловой системы}», в противном случае также будет выдано исключение UnsupportedOperationException.
Path path = Paths.get("/data/logs/web.log");
UserDefinedFileAttributeView view = Files.getFileAttributeView(path,UserDefinedFileAttributeView.class);
String name = "user.mimetype";
int size = view.size(name);//我个人认为JDK应该直接支持获取属性值,而不是再周折一番
ByteBuffer buffer = ByteBuffer.allocate(size);
view.read(name,buffer);
buffer.flip();
String value = Charset.defaultCharset().decode(buffer).toString();
System.out.println(value);
//其他操作,比如list获取所有属性的列表等。
//写入或者跟新自定义属性
view.write(name,Charset.defaultCharset().encode("text/html"));
3. Файловая система
FileStore — это новый API, используемый для описания базовой системы хранения.На платформе есть несколько FileStore.Мы можем получить список FileStore, а также состояние хранилища и список файлов каждого хранилища через FileSystem.
Path path = Paths.get("/data/logs/web.log");
path.getFileSystem().getFileStores();//获取文件所属的文件系统的所有的存储器。
//当前文件系统所能支持的FileAttributeView,此后可以对文件使用相应的view获取或者修改属性
Set<String> viewNames = FileSystems.getDefault().supportedFileAttributeViews();
System.out.println(viewNames);//basic,unix,posix,owner,dos等
//或者,全局
//遍历所有的磁盘存储
Iterable<FileStore> fileStores = FileSystems.getDefault().getFileStores();//获取默认文件系统的所有存储器
for(FileStore store : fileStores) {
System.out.println("\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-");
System.out.println("className:" + store.getClass().getName());
System.out.println("name:" + store.name());//磁盘名称
System.out.println("type:" + store.type());//类型
System.out.println("readOnly:" + store.isReadOnly());//是否为只读
System.out.println("usableSpace:" + store.getUsableSpace() + "/" + store.getTotalSpace());
boolean supported = store.supportsFileAttributeView(BasicFileAttributeView.class);
//或者
//boolean supported = store.supportsFileAttributeView("basic");
//fileStore的属性,不同于FileAttributes,这些属性应该与FileStore的各个实现类对应。
Long totalSpace = (Long)store.getAttribute("totalSpace");
System.out.println(totalSpace);
Вы можете получить FileAttributeView, поддерживаемый каждым FileStore, а затем вы можете получить соответствующий класс представления с помощью Files.getFileAttributeView(). Каждое представление имеет сокращенное имя, например, BasicFileAttributeView.name() возвращает сокращенное имя как «базовое». В настоящее время JDK поддерживает многие FileAttributeView, такие как BasicFileAttributeView, UnixFileAttributeView и т. д., а также UserDefinedFileAttributeView, который позволяет выполнять настройку. JDK реализует операции получения и изменения атрибутов файла на основе соответствующего класса FileAttributeView.
PosixFileAttributeView view = Files.getFileAttributeView(path,PosixFileAttributeView.class);
PosixFileAttributes fileAttributes = view.readAttributes();
Кроме того, в зависимости от базового хранилища FileStore существуют различные реализации.Вы можете обратиться к классам реализации FileStore, таким как UnixFileStore, BsfFileStore (Mac) и т. д. должен быть основан на соответствующем классе реализации.Для получения вы также можете использовать FileStore.getAttribute() для получения, но имя атрибута должно соответствовать имени атрибута, поддерживаемому в классе.
4. Работа со справочником
Каталог в JAVA также представлен путем, а его основные атрибуты такие же, как у файла.
4.1. Список корневого каталога
//遍历文件系统的所有根目录
Iterable<Path> roots = FileSystems.getDefault().getRootDirectories();
for(Path root : roots) {
System.out.print(root);
}
4.2, создать, удалить
Path dir = Paths.get("/data/xyz");
Files.createDirectories(dir);
Files.createDirectory(dir);
Метод createDirectory() является методом «строгой проверки». Если родительский путь не существует, будет выдано исключение. Если путь уже существует или существует файл с таким же именем, будет выдано исключение. Короче говоря, этот метод может создать только каталог последнего уровня (ранее он не существовал). Для метода createDirectories() он более совместим, он будет проверять и создавать родительский путь слой за слоем и создавать его, если он не существует.
При создании каталога вы также можете указать атрибуты файла (включая разрешения), такие как файл.
Path dir = Paths.get("/data/xyz/12x/123x");
Set<PosixFilePermission> permissions = PosixFilePermissions.fromString("\-rw\-rw\-\-\-\-");
FileAttribute<Set<PosixFilePermission>> fileAttribute = PosixFilePermissions.asFileAttribute(permissions);
Files.createDirectories(dir,fileAttribute);
4.3, обход каталога
Path dir = Paths.get("/data");
DirectoryStream<Path> stream = Files.newDirectoryStream(dir);
for (Path path : stream) {
System.out.println(path);
}
stream.close();
Метод потока будет проходить по всем файлам в указанном каталоге, включая файлы. содержание. Подключить, скрыть файлы или каталоги и т. д.
Кроме того, JDK также поддерживает режим на основе фильтров для фильтрации «несущественных» файлов или каталогов во время обхода.
Path dir = Paths.get("/data");
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
@Override
public boolean accept(Path entry) throws IOException {
return Files.isRegularFile(entry);
}
};
DirectoryStream<Path> stream = Files.newDirectoryStream(dir,filter);
for (Path path : stream) {
System.out.println(path);
}
stream.close();
4.4, фильтр глобальных файлов
В NIO2 добавлена поддержка файловых фильтров на основе Glob, синтаксис сопоставления аналогичен регулярным выражениям; glob — это выражение из unlix (команда оболочки) для сопоставления файлов, многие основные языки и платформы (dos, window) Поддерживаются оба, но разные языки имеют разные уровни поддержки glob (обратите внимание).
1,*: соответствует любому количеству произвольных символов, включая нулевой символ (нет). Например, «/data/*.log» соответствует всем файлам в каталоге «data», которые заканчиваются на «.log».
2,**: Подобно *, соответствует любому количеству символов, но может обходить разделители каталогов. Этот синтаксис обычно используется для соответствия полным путям. Например: "/данные/**"
3.?: соответствует только одному символу.
4.\: экранирующий символ, используемый для экранирования специальных символов, таких как «\», «-», «{», «}», «[» и т. д. Например, если вам нужно сопоставить «{», то его буквальное выражение — «\{», а «\\» используется для соответствия одиночной косой черте.
5.!: нет, не содержит, обычно используется с []. (Похоже, он не поддерживает ^)
6.{}: укажите набор подправил, таких как:
1){sum,moon,stars}: Соответствует «солнцу», «луне» или «началу» (подходит одно из них), а подправила разделяются знаком «,».
2){temp*,tmp*}: соответствует всем строкам, начинающимся с temp или tmp.
7.[]: соответствует одному символу в наборе строк, если набор строк содержит «-», он соответствует одному символу в интервале. Например, [abc] соответствует "a", "b" или "c", [a-z] соответствует одному из символов нижнего регистра от a до z, а [0-9] соответствует любому числу от 0 до 9. Можно смешать, например, [abce-g] соответствует "a", "b", "c", "e", "f", "g", [!ac] соответствует любому символу, кроме символов a, b, c. . Составные подправила разделяются символом ",", например [a-z,0-9] соответствует любому символу a~z или 0~9.
В [] "*", "?", "\" соответствуют только самим себе (буквально), а также соответствуют самим себе, если "-" находится внутри [] и является первым символом или после!.
8. Начальные символы и «.» в файле будут рассматриваться как обычные символы. Например, «*» может соответствовать файлу «.tmp», а FIles.isHidden() можно использовать для обнаружения этого файла как скрытого.
9. Все остальные символы совпадают сами с собой (в зависимости от реализации на платформе, включая разделители путей и т. д.).
Пример:
1. *.html соответствует любому файлу, оканчивающемуся на «.html».
2. ???: соответствует любым трем символам (включая цифры)
3. *[0-9]*: соответствует любому количеству символов, содержащих число.
4. *.{htm,html} соответствует любой строке, оканчивающейся на "html" или "htm".
Выражение GLobbing, относительно удобная стратегия фильтрации, для некоторых простых операций (в основном при сопоставлении только по характеристикам имени файла или пути) может выполняться без использования Filter, разумеется, внутренняя реализация glob по-прежнему основана на инкапсуляции Filter to достижения (PathMatcher); но синтаксис glob относительно прост, и JDK NIO2 может поддерживать как glob, так и регулярные выражения для выражений фильтрации файлов. Как использовать PathMatcher для обхода дерева файлов или каталогов, будет описано позже.
Path dir = Paths.get("/data");
//内部,默认会对glob表达式增加前缀,glob,为了兼容PathMatcher
DirectoryStream<Path> stream = Files.newDirectoryStream(dir,"\*.txt");
for (Path path : stream) {
System.out.println(path);
}
stream.close();
4.5 Файл ссылки на операцию
Проводные (или подключенные):
1) файлы имеют одинаковый индекс и блок данных;
2) Можно создавать только существующие файлы;
3) нельзя создавать жесткие ссылки между файловыми системами;
4) Нельзя создать каталог, можно создать только файл;
5) Удаление файла с жесткой ссылкой не влияет на другие файлы с таким же номером инода.
Мягкая ссылка (символическая ссылка): Мягкая ссылка отличается от жесткой ссылки.Если содержимое, хранящееся в пользовательском блоке данных файла, указывает на путь к другому файлу, файл является мягкой ссылкой. Мягкая ссылка — это обычный файл, но содержимое блока данных немного отличается. Программные ссылки имеют свои собственные номера инодов и пользовательские блоки данных. Поэтому создание и использование мягких ссылок не имеет многих ограничений, подобных жестким ссылкам:
1) Программные ссылки имеют собственные атрибуты файлов и права доступа;
2) Мягкие ссылки могут быть созданы на несуществующие файлы или каталоги;
3) программные ссылки могут пересекать файловые системы;
4) Мягкие ссылки могут быть созданы для файлов или каталогов;
5) При создании софтлинка счетчик ссылок i_nlink не будет увеличиваться;
6) Удаление программной ссылки не влияет на указанный файл, но если указанный исходный файл удаляется, соответствующая программная ссылка называется мертвой ссылкой (т. е. оборванной ссылкой, если файл указанного пути воссоздан, мертвую ссылку можно восстановить). для обычных программных ссылок).
##创建连接
ln 目标 连接名
## 创建软连接
ln \-s 目标 连接名
##查看软连接目标指向,对于硬连接是不显示。
ls \-l 软连接文件
##通过stat指令可以查看软硬连接的inode和block信息
##发现硬连接与目标文件的信息完全一致。
##软连接文件有单独的inode和block。
Создать соединение
Path target = Paths.get("/data/test.log");
//target必须存在
Files.createLink(Paths.get("/data/hard\-link.log"),target);
Files.createSymbolicLink(Paths.get("/data/soft\-link.log"),target);
//检测文件是否为软连接问题
boolean isSymbolicLink = Files.isSymbolicLink(Paths.get("/data/soft\-link.log"));
Path target2 = Files.readSymbolicLink(Paths.get("/data/soft\-link.log"));
//检测是否为同一个文件
System.out.println(Files.isSameFile(target,target2));//true
System.out.println(Files.isSameFile(target,Paths.get("/data/hard\-link.log")));//true
System.out.println(Files.isSameFile(target,Paths.get("/data/soft\-link.log")));//true
通过Files.isSameFile()比较,我们会发现,无论是软连接、硬链接,都与目标文件是同一个文件。
4.6, найти файлы
В предыдущей статье был представлен PathMatcher, выражение, используемое для сопоставления файлов в JAVA NIO2, которое может поддерживать glob и регулярные выражения (регулярные выражения). Синтаксис glob ближе к оболочке linux, а regex — более широкий и богатый способ. Например файл: /data/test.log
Path path = Paths.get("/data/test.log");
PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:\*\*.log");
System.out.println(pathMatcher.matches(path));
//基于正则
pathMatcher = FileSystems.getDefault().getPathMatcher("regex:.\*\\\\.log");
System.out.println(pathMatcher.matches(path));
Правила выражения: синтаксис:шаблон, где допустимым синтаксисом является "glob" и "regex"; обратите внимание на разницу между этими двумя выражениями. Внутренняя реализация также относительно проста: для строки glob она будет преобразована в строку регулярного выражения, а затем единообразно будет использоваться регулярное сопоставление.
4.7, рекурсивный обход дерева каталогов
Раньше было сложно просматривать количество файлов с помощью JAVA, но эта операция была изначально добавлена в NIO2. Основной API — FileVisitor, а его простой класс реализации — SimpleFileVisitor:
1. preVisitDirectory: перед просмотром каталога. Предварительная операция. Например, при просмотре и копировании файлов вы можете создать новый каталог для цели миграции перед входом в каталог.
2. postVisitDirectory: после просмотра всех файлов в каталоге (перед просмотром других каталогов). Пост операция.
3, visitFile: просмотрите файлы, Path и BaseFileAttributes будут переданы в метод.
4. visitFileFailed: вызывается при сбое просмотра файла, например, когда атрибут файла не может быть получен, каталог не может быть открыт и т. д., этот метод вызывается, и одновременно передаются путь и исключение.
Простой обход (найти, отфильтровать совпадения)
Path dir = Paths.get("/data/redis");
Stream<Path> stream = Files.walk(dir);
stream.forEach(path \-> {
System.out.println(path);
});
stream.close();
Комплексный обход (поиск обхода, проверка переноса файлов)
public static void main(String\[\] args) throws Exception{
Path dir = Paths.get("/data/redis");
Files.walkFileTree(dir,new Finder());
}
public static class Finder implements FileVisitor<Path> {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
System.out.println("preVisitDirectory:" + dir);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println("visitFile:" + file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
System.out.println("visitFileFailed:" + file + ",exception:" + (exc != null ? exc.getMessage() : "\-"));
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
System.out.println("postVisitDirectory:" + dir);
return FileVisitResult.CONTINUE;
}
}
FileVisitResult используется для представления статуса выполнения:
1)CONTINUE: Указывает на продолжение выполнения (переход к следующему шагу)
2)TERMINATE: Завершить рекурсивный обход, другие последующие методы не будут выполняться, а файлы, которые не были просмотрены, не будут доступны.
3)SKIP_SUBTREE: Пропустить поддерево, т. е. текущий каталог и его подкаталоги будут пропущены. Применяется к preVisitDirectory(), другие методы, возвращающие это значение, эквивалентны CONTINUE.
4)SKIP_SIBLINGS: Пропустить родственный файл или файл этого файла (или каталога), применимо к postVisitDirectory(), если preVisitDirectory возвращает это значение, текущий каталог также будет пропущен, а postVisitDirectory() не будет выполняться.
End
Ну а по поводу нового API NIO2 введение завершено.
Вам стало легче?
:) Спасибо за вклад Ню Цао Эр.
Об авторе:Мисс сестра вкус(xjjdog), публичная учетная запись, которая не позволяет программистам идти в обход. Сосредоточьтесь на инфраструктуре и Linux. Десять лет архитектуры, десятки миллиардов ежедневного трафика, обсуждение с вами мира высокой параллелизма, дающие вам другой вкус. Мой личный WeChat xjjdog0, добро пожаловать в друзья для дальнейшего общения.