清理残留的 java.io.File 用例 (#4503)

This commit is contained in:
Glavo 2025-09-18 15:26:03 +08:00 committed by GitHub
parent 45f7719096
commit a0568e34a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 67 additions and 65 deletions

View File

@ -20,10 +20,13 @@ package org.jackhuang.hmcl.java;
import kala.compress.archivers.ArchiveEntry;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.DigestUtils;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jackhuang.hmcl.util.io.IOUtils;
import org.jackhuang.hmcl.util.tree.ArchiveFileTree;
import java.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@ -98,8 +101,7 @@ public final class JavaInstallTask extends Task<JavaManifest> {
}
if (tree.isExecutable(entry))
//noinspection ResultOfMethodCallIgnored
path.toFile().setExecutable(true);
FileUtils.setExecutable(path);
files.put(String.join("/", nameStack), new JavaLocalFiles.LocalFile(HexFormat.of().formatHex(messageDigest.digest()), size));
}

View File

@ -77,12 +77,16 @@ import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.ref.WeakReference;
import java.net.*;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
@ -457,22 +461,27 @@ public final class FXUtils {
}
}
public static void openFolder(File file) {
public static void openFolder(Path file) {
if (file.getFileSystem() != FileSystems.getDefault()) {
LOG.warning("Cannot open folder as the file system is not supported: " + file);
return;
}
try {
Files.createDirectories(file.toPath());
Files.createDirectories(file);
} catch (IOException e) {
LOG.warning("Failed to create directory " + file);
return;
}
String path = file.getAbsolutePath();
String path = FileUtils.getAbsolutePath(file);
String openCommand;
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS)
openCommand = "explorer.exe";
else if (OperatingSystem.CURRENT_OS == OperatingSystem.MACOS)
openCommand = "/usr/bin/open";
else if (OperatingSystem.CURRENT_OS.isLinuxOrBSD() && new File("/usr/bin/xdg-open").exists())
else if (OperatingSystem.CURRENT_OS.isLinuxOrBSD() && Files.exists(Path.of("/usr/bin/xdg-open")))
openCommand = "/usr/bin/xdg-open";
else
openCommand = null;
@ -494,7 +503,7 @@ public final class FXUtils {
// Fallback to java.awt.Desktop::open
try {
java.awt.Desktop.getDesktop().open(file);
java.awt.Desktop.getDesktop().open(file.toFile());
} catch (Throwable e) {
LOG.error("Unable to open " + path + " by java.awt.Desktop.getDesktop()::open", e);
}
@ -537,11 +546,11 @@ public final class FXUtils {
}
// Fallback to open folder
openFolder(file.getParent().toFile());
openFolder(file.getParent());
});
} else {
// We do not have a universal method to show file in file manager.
openFolder(file.getParent().toFile());
openFolder(file.getParent());
}
}
@ -1449,13 +1458,6 @@ public final class FXUtils {
return String.format("#%02x%02x%02x", r, g, b);
}
public static @Nullable List<Path> showOpenMultipleDialog(FileChooser chooser, Window ownerWindow) {
List<File> files = chooser.showOpenMultipleDialog(ownerWindow);
if (files == null)
return null;
return files.stream().map(File::toPath).toList();
}
public static FileChooser.ExtensionFilter getImageExtensionFilter() {
return new FileChooser.ExtensionFilter(i18n("extension.png"),
IMAGE_EXTENSIONS.stream().map(ext -> "*." + ext).toArray(String[]::new));

View File

@ -52,7 +52,7 @@ import org.jackhuang.hmcl.util.platform.Architecture;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
import org.jackhuang.hmcl.util.platform.Platform;
import java.io.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
@ -111,9 +111,9 @@ public final class JavaManagementPage extends ListPageBase<JavaManagementPage.Ja
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS)
chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Java", "java.exe"));
chooser.setTitle(i18n("settings.game.java_directory.choose"));
File file = chooser.showOpenDialog(Controllers.getStage());
Path file = FileUtils.toPath(chooser.showOpenDialog(Controllers.getStage()));
if (file != null) {
JavaManager.getAddJavaTask(file.toPath()).whenComplete(Schedulers.javafx(), exception -> {
JavaManager.getAddJavaTask(file).whenComplete(Schedulers.javafx(), exception -> {
if (exception != null) {
LOG.warning("Failed to add java", exception);
Controllers.dialog(i18n("java.add.failed"), i18n("message.error"), MessageDialogPane.MessageType.ERROR);

View File

@ -236,7 +236,7 @@ public abstract class SettingsView extends StackPane {
}
public void openLogFolder() {
FXUtils.openFolder(LOG.getLogFile().getParent().toFile());
FXUtils.openFolder(LOG.getLogFile().getParent());
}
protected abstract void onUpdate();

View File

@ -33,7 +33,7 @@ import org.jackhuang.hmcl.ui.construct.SpinnerPane;
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
import org.jackhuang.hmcl.util.StringUtils;
import java.io.*;
import java.io.IOException;
import java.nio.file.Path;
import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed;

View File

@ -25,7 +25,11 @@ import com.github.steveice10.opennbt.tag.builtin.Tag;
import kala.compress.utils.BoundedInputStream;
import org.jackhuang.hmcl.util.io.FileUtils;
import java.io.*;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;

View File

@ -175,7 +175,7 @@ public final class ModListPage extends ListPageBase<ModListPageSkin.ModInfoObjec
}
public void openModFolder() {
FXUtils.openFolder(profile.getRepository().getRunDirectory(versionId).resolve("mods").toFile());
FXUtils.openFolder(profile.getRepository().getRunDirectory(versionId).resolve("mods"));
}
public void checkUpdates() {

View File

@ -365,7 +365,7 @@ public final class SchematicsPage extends ListPageBase<SchematicsPage.Item> impl
@Override
void onReveal() {
FXUtils.openFolder(path.toFile());
FXUtils.openFolder(path);
}
@Override

View File

@ -157,7 +157,7 @@ public class VersionPage extends DecoratorAnimatedPage implements DecoratorPage
}
private void onBrowse(String sub) {
FXUtils.openFolder(getProfile().getRepository().getRunDirectory(getVersion()).resolve(sub).toFile());
FXUtils.openFolder(getProfile().getRepository().getRunDirectory(getVersion()).resolve(sub));
}
private void redownloadAssetIndex() {

View File

@ -142,7 +142,7 @@ public final class Versions {
}
public static void openFolder(Profile profile, String version) {
FXUtils.openFolder(profile.getRepository().getRunDirectory(version).toFile());
FXUtils.openFolder(profile.getRepository().getRunDirectory(version));
}
public static void duplicateVersion(Profile profile, String version) {

View File

@ -87,7 +87,7 @@ public final class WorldListItem extends Control {
}
public void reveal() {
FXUtils.openFolder(world.getFile().toFile());
FXUtils.openFolder(world.getFile());
}
public void showManagePage() {

View File

@ -117,7 +117,7 @@ public final class WorldManagePage extends DecoratorAnimatedPage implements Deco
JFXPopup.PopupVPosition.BOTTOM, JFXPopup.PopupHPosition.LEFT,
chunkBaseMenuItem.getWidth(), 0)));
}
toolbar.addNavigationDrawerItem(i18n("settings.game.exploration"), SVG.FOLDER_OPEN, () -> FXUtils.openFolder(world.getFile().toFile()), null);
toolbar.addNavigationDrawerItem(i18n("settings.game.exploration"), SVG.FOLDER_OPEN, () -> FXUtils.openFolder(world.getFile()), null);
BorderPane.setMargin(toolbar, new Insets(0, 0, 12, 0));
left.setBottom(toolbar);

View File

@ -27,6 +27,7 @@ import org.jackhuang.hmcl.task.GetTask;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.ChecksumMismatchException;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jackhuang.hmcl.util.platform.UnsupportedPlatformException;
import org.tukaani.xz.LZMAInputStream;
@ -119,7 +120,7 @@ public final class MojangJavaDownloadTask extends Task<MojangJavaDownloadTask.Re
Files.move(decompressed, dest, StandardCopyOption.REPLACE_EXISTING);
if (file.isExecutable()) {
dest.toFile().setExecutable(true);
FileUtils.setExecutable(dest);
}
}));
} else if (file.getDownloads().containsKey("raw")) {
@ -127,7 +128,7 @@ public final class MojangJavaDownloadTask extends Task<MojangJavaDownloadTask.Re
var task = new FileDownloadTask(downloadProvider.injectURLWithCandidates(download.getUrl()), dest, new FileDownloadTask.IntegrityCheck("SHA-1", download.getSha1()));
task.setName(entry.getKey());
if (file.isExecutable()) {
dependencies.add(task.thenRunAsync(() -> dest.toFile().setExecutable(true)));
dependencies.add(task.thenRunAsync(() -> FileUtils.setExecutable(dest)));
} else {
dependencies.add(task);
}

View File

@ -736,7 +736,8 @@ public class DefaultLauncher extends Launcher {
}
}
}
if (!scriptFile.toFile().setExecutable(true))
FileUtils.setExecutable(scriptFile);
if (!Files.isExecutable(scriptFile))
throw new PermissionException();
if (usePowerShell && !CommandBuilder.hasExecutionPolicy())

View File

@ -223,7 +223,8 @@ public class CacheRepository {
return cacheData(connection, () -> {
String hash = DigestUtils.digestToString(SHA1, bytes);
Path cached = getFile(SHA1, hash);
FileUtils.writeBytes(cached, bytes);
Files.createDirectories(cached.getParent());
Files.write(cached, bytes);
return new CacheResult(hash, cached);
});
}

View File

@ -29,6 +29,8 @@ import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFilePermission;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
@ -236,36 +238,6 @@ public final class FileUtils {
return new String(bytes, OperatingSystem.NATIVE_CHARSET);
}
/**
* Write plain text to file. Characters are encoded into bytes using UTF-8.
* <p>
* We don't care about platform difference of line separator. Because readText accept all possibilities of line separator.
* It will create the file if it does not exist, or truncate the existing file to empty for rewriting.
* All characters in text will be written into the file in binary format. Existing data will be erased.
*
* @param file the path to the file
* @param text the text being written to file
* @throws IOException if an I/O error occurs
*/
public static void writeText(Path file, String text) throws IOException {
Files.createDirectories(file.getParent());
Files.writeString(file, text);
}
/**
* Write byte array to file.
* It will create the file if it does not exist, or truncate the existing file to empty for rewriting.
* All bytes in byte array will be written into the file in binary format. Existing data will be erased.
*
* @param file the path to the file
* @param data the data being written to file
* @throws IOException if an I/O error occurs
*/
public static void writeBytes(Path file, byte[] data) throws IOException {
Files.createDirectories(file.getParent());
Files.write(file, data);
}
public static void deleteDirectory(Path directory) throws IOException {
if (!Files.exists(directory))
return;
@ -285,6 +257,24 @@ public final class FileUtils {
}
}
public static void setExecutable(Path path) {
PosixFileAttributeView view = Files.getFileAttributeView(path, PosixFileAttributeView.class);
if (view != null) {
try {
Set<PosixFilePermission> oldPermissions = view.readAttributes().permissions();
if (oldPermissions.contains(PosixFilePermission.OWNER_EXECUTE))
return;
EnumSet<PosixFilePermission> permissions = EnumSet.noneOf(PosixFilePermission.class);
permissions.addAll(oldPermissions);
permissions.add(PosixFilePermission.OWNER_EXECUTE);
view.setPermissions(permissions);
} catch (IOException e) {
LOG.warning("Failed to set permissions for " + path, e);
}
}
}
/**
* Copy directory.
* Paths of all files relative to source directory will be the same as the ones relative to destination directory.
@ -397,7 +387,8 @@ public final class FileUtils {
FileUtils.copyFile(file, targetFile);
}
FileUtils.writeText(infoFile, "[Trash Info]\nPath=" + file.toAbsolutePath().normalize() + "\nDeletionDate=" + time + "\n");
Files.createDirectories(infoDir);
Files.writeString(infoFile, "[Trash Info]\nPath=" + FileUtils.getAbsolutePath(file) + "\nDeletionDate=" + time + "\n");
FileUtils.forceDelete(file);
} catch (IOException e) {
LOG.warning("Failed to move " + file + " to trash", e);