Как программно изменить права доступа к файлам?

115

В Java я динамически создаю набор файлов, и мне хотелось бы изменить права доступа к этим файлам в файловой системе linux / unix. Я хотел бы иметь возможность выполнять Java-эквивалент chmod. Возможна ли Java 5? Если да, то как?

Я знаю, что в Java 6 у Fileобъекта есть setReadable()/ setWritable()методы. Я также знаю, что могу сделать это системным вызовом, но по возможности я бы хотел этого избежать.

Рой Рико
источник
2
Примечание для других: для существующих файлов, начиная с Java 7, вы можете использовать этот однострочник:Files.setPosixFilePermissions(path, PosixFilePermissions.fromString("rwxr-x---"))
tom

Ответы:

110

Полный контроль над атрибутами файлов доступен в Java 7 как часть «нового» средства New IO ( NIO.2 ). Например, разрешение POSIX может быть установлено на существующий файл setPosixFilePermissions(), или атомарном при создании файла с методами , как createFile()или newByteChannel().

Вы можете создать набор разрешений, используя EnumSet.of(), но вспомогательный метод PosixFilePermissions.fromString()будет использовать обычный формат, который будет более читабельным для многих разработчиков. Для API, которые принимают a FileAttribute, вы можете заключить набор разрешений вPosixFilePermissions.asFileAttribute() .

Set<PosixFilePermission> ownerWritable = PosixFilePermissions.fromString("rw-r--r--");
FileAttribute<?> permissions = PosixFilePermissions.asFileAttribute(ownerWritable);
Files.createFile(path, permissions);

В более ранних версиях Java execраспространенным подходом является использование собственного нативного кода или утилит командной строки -ing.

Эриксон
источник
4
выбрав этот, поскольку у меня нет возможности использовать ответ Марти Лэмба.
Рой Рико,
1
Я серьезно не могу поверить, что прошло более шести лет с тех пор, как они начали работать над NIO.2, а он все еще не входит в состав JRE.
Clee 03
8
В вашем ответе может быть полезен пример кода.
Рикардо Гладуэлл,
2
Этот ответ stackoverflow.com/a/32331442/290182 от @PixelsTech лучше, поскольку он предоставляет пример кода
beldaz
1
@SteveB Все готово.
erickson
43

В дополнение к предложениям Эриксона есть также jna , которая позволяет вам вызывать собственные библиотеки без использования jni. Он потрясающе прост в использовании, и я успешно использовал его в нескольких проектах.

Единственное предостережение - это медленнее, чем jni, поэтому, если вы делаете это с очень большим количеством файлов, это может быть проблемой для вас.

(Редактирование для добавления примера)

Вот полный пример jna chmod:

import com.sun.jna.Library;
import com.sun.jna.Native;

public class Main {
    private static CLibrary libc = (CLibrary) Native.loadLibrary("c", CLibrary.class);

    public static void main(String[] args) {
        libc.chmod("/path/to/file", 0755);
    }
}

interface CLibrary extends Library {
    public int chmod(String path, int mode);
}
Марти Лэмб
источник
1
JNA - отличный инструмент для нативных вызовов!
erickson
3
Для правильной обработки ошибок необходимо объявить CLibrary.chmod () для выдачи исключения com.sun.jna.LastErrorException. Это единственный потокобезопасный способ получить значение errno, установленное вызовом chmod (). В противном случае вы можете получить статус успеха / неудачи из возвращаемого значения, но не фактический код ошибки.
Саймон Киссане
30

До Java 6 не было поддержки обновления прав доступа к файлам на уровне Java. Вы должны реализовать свой собственный собственный метод или вызвать Runtime.exec()команду уровня ОС, такую ​​как chmod .

Начиная с Java 6, вы можете использовать File.setReadable()/File.setWritable()/File.setExecutable()для установки прав доступа к файлам. Но он не имитирует файловую систему POSIX, которая позволяет устанавливать разрешения для разных пользователей. File.setXXX () позволяет установить разрешение только для владельца и всех остальных.

Начиная с Java 7, вводятся права доступа к файлам POSIX. Вы можете установить права доступа к файлам, как в системах * nix. Синтаксис:

File file = new File("file4.txt");
file.createNewFile();

Set<PosixFilePermission> perms = new HashSet<>();
perms.add(PosixFilePermission.OWNER_READ);
perms.add(PosixFilePermission.OWNER_WRITE);

Files.setPosixFilePermissions(file.toPath(), perms);

Этот метод можно использовать только в файловой системе POSIX, это означает, что вы не можете вызывать его в системе Windows.

Для получения подробной информации об управлении разрешениями файлов, рекомендуем вам прочитать этот пост .

PixelsTech
источник
18

для windows 7 с nio 2.0:

public static void main(String[] args) throws IOException
{
    Path file = Paths.get("c:/touch.txt");
    AclFileAttributeView aclAttr = Files.getFileAttributeView(file, AclFileAttributeView.class);
    System.out.println(aclAttr.getOwner());
    for(AclEntry aclEntry : aclAttr.getAcl()){
        System.out.println(aclEntry);
    }
    System.out.println();

    UserPrincipalLookupService upls = file.getFileSystem().getUserPrincipalLookupService();
    UserPrincipal user = upls.lookupPrincipalByName(System.getProperty("user.name"));
    AclEntry.Builder builder = AclEntry.newBuilder();       
    builder.setPermissions( EnumSet.of(AclEntryPermission.READ_DATA, AclEntryPermission.EXECUTE, 
            AclEntryPermission.READ_ACL, AclEntryPermission.READ_ATTRIBUTES, AclEntryPermission.READ_NAMED_ATTRS,
            AclEntryPermission.WRITE_ACL, AclEntryPermission.DELETE
    ));
    builder.setPrincipal(user);
    builder.setType(AclEntryType.ALLOW);
    aclAttr.setAcl(Collections.singletonList(builder.build()));
}
боб
источник
1
это отлично работает. Единственная модификация была сделана для метода lookupPrincipalByName (), я отправил System.getProperty ("user.name") вместо "user". Наконец, это выглядело как upls.lookupPrincipalByName (System.getProperty ("user.name")); Спасибо за код!
isuru chathuranga 06
@bob .. не могли бы вы дать мне класс AclFileAttributeView и UserPrincipalLookupService .. bcz он не может разрешить .. ваш ответ, похоже, работает .. и я хочу реализовать
Сагар Чавада 08
java.nio.file.attribute.AclFileAttributeView и java.nio.file.attribute.UserPrincipalLookupService, для компиляции и запуска требуется jdk 1.7+.
bob
11

Если вы хотите установить разрешение 777 для созданного файла, вы можете использовать следующий метод:

public void setPermission(File file) throws IOException{
    Set<PosixFilePermission> perms = new HashSet<>();
    perms.add(PosixFilePermission.OWNER_READ);
    perms.add(PosixFilePermission.OWNER_WRITE);
    perms.add(PosixFilePermission.OWNER_EXECUTE);

    perms.add(PosixFilePermission.OTHERS_READ);
    perms.add(PosixFilePermission.OTHERS_WRITE);
    perms.add(PosixFilePermission.OTHERS_EXECUTE);

    perms.add(PosixFilePermission.GROUP_READ);
    perms.add(PosixFilePermission.GROUP_WRITE);
    perms.add(PosixFilePermission.GROUP_EXECUTE);

    Files.setPosixFilePermissions(file.toPath(), perms);
}
Апурв Чурасия
источник
10

Просто чтобы обновить этот ответ, если кто-нибудь не столкнется с этим позже, поскольку JDK 6 вы можете использовать

File file = new File('/directory/to/file');
file.setWritable(boolean);
file.setReadable(boolean);
file.setExecutable(boolean);

вы можете найти документацию по Oracle File (Java Platform SE 7) . Имейте в виду, что эти команды работают только в том случае, если текущий рабочий пользователь имеет право собственности или права записи в этот файл. Я знаю, что OP хотел получить доступ к типу chmod для более сложной конфигурации пользователя. они установят опцию для всех пользователей.

TravisF
источник
Круто, le sauveur!
хаваризми
Я еще тестировал его с Openjdk 11.0.6 под Debian, он работает!
Хартмут Шорриг,
4

Вы можете использовать методы класса File: http://docs.oracle.com/javase/7/docs/api/java/io/File.html

Эрел Сегал-Халеви
источник
3
Пожалуйста, еще раз взгляните на вопрос. Рой Рико знает о setReadable () и setWritable (), но они позволяют изменять только права владельца, а не права группы или всех, или любые другие флаги.
ChrisB 05
3

для Oralce Java 6:

private static int chmod(String filename, int mode) {
    try {
        Class<?> fspClass = Class.forName("java.util.prefs.FileSystemPreferences");
        Method chmodMethod = fspClass.getDeclaredMethod("chmod", String.class, Integer.TYPE);
        chmodMethod.setAccessible(true);
        return (Integer)chmodMethod.invoke(null, filename, mode);
    } catch (Throwable ex) {
        return -1;
    }
}

работает под Solaris / linux.

Влад
источник
следует знать, что FileSystemPreferencesпоток Timerдемона распространяется после его загрузки. он также добавляет ловушку выключения, но для некоторых приложений это может быть проблематично.
thrau
2

Apache ant chmod (не очень элегантный, добавлен для полноты) предоставлен @msorsky

    Chmod chmod = new Chmod();
    chmod.setProject(new Project());
    FileSet mySet = new FileSet();
    mySet.setDir(new File("/my/path"));
    mySet.setIncludes("**");
    chmod.addFileset(mySet);
    chmod.setPerm("+w");
    chmod.setType(new FileDirBoth());
    chmod.execute();
ihadanny
источник
1
simple java code  for change file permission in java  

   String path="D:\\file\\read.txt";
        File file=new File(path);
        if (file.exists()) {
            System.out.println("read="+file.canRead());
            System.out.println("write="+file.canWrite());
            System.out.println("Execute="+file.canExecute());
            file.setReadOnly();
        }     

Ссылка: как изменить разрешение файла в java

Анудж Дхиман
источник
0
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Set;

public class FileAndDirectory1 {
    public static void main(String[] args) {
        
        File file = new File("fileTest1.txt");
        System.out.println(file.getAbsoluteFile());
        try {
            //file.createNewFile();
            if(!file.exists())
            {
                //PosixFilePermission is an enum class, PosixFilePermissions is a final class
                
                //create file permissions from string
                Set<PosixFilePermission> filePermissions = PosixFilePermissions.fromString("---------"/* "rwxrwxrwx" */);
                FileAttribute<?> permissions = PosixFilePermissions.asFileAttribute(filePermissions);
                Files.createFile(file.toPath(), permissions);
                // printing the permissions associated with the file
                System.out.println("Executable: " + file.canExecute());
                System.out.println("Readable: " + file.canRead());
                System.out.println("Writable: "+ file.canWrite());

                file.setExecutable(true);
                file.setReadable(true);
                file.setWritable(true);
            }
            else
            {
                //modify permissions
                
                //get the permission using file attributes
                Set<PosixFilePermission> perms = Files.readAttributes(file.toPath(), PosixFileAttributes.class).permissions();
                perms.remove(PosixFilePermission.OWNER_WRITE);

                perms.add(PosixFilePermission.OWNER_READ);
                perms.add(PosixFilePermission.OWNER_EXECUTE);
                perms.add(PosixFilePermission.GROUP_WRITE);
                perms.add(PosixFilePermission.GROUP_READ);
                perms.add(PosixFilePermission.GROUP_EXECUTE);
                perms.add(PosixFilePermission.OTHERS_WRITE);
                perms.add(PosixFilePermission.OTHERS_READ);
                perms.add(PosixFilePermission.OTHERS_EXECUTE);
                Files.setPosixFilePermissions(file.toPath(), perms);

                System.out.println("Executable: " + file.canExecute());
                System.out.println("Readable: " + file.canRead());
                System.out.println("Writable: "+ file.canWrite());

                file.delete();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        Path path = Paths.get(String.valueOf(file));
        System.out.println(path);
    }
}
Уддхав Гаутам
источник