/*
* #######################################################
*
* Copyright (c) 2013, A. Weinberger. All rights reserved.
* --------------------------------------------------------
*/
package ale.util.fileUtil;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.security.InvalidParameterException;
import java.util.Iterator;
import java.util.List;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;
import ale.Constants;
import ale.controller.Main;
/**
* ------------------------------------------------- <br/>
* Package: ale.util.fileUtil <br/>
* Class : FileUtil <br/>
* --------------------------- <br/>
* <br/>
* The <code>FileUtil</code> class contains helpermethods to handle files. <br/>
* <br/>
* <br/>
* Last edited: 23.04.2013 <br/>
* ------------------------------------------------- <br/>
*/
public final class FileUtil {
private static final int BYTE = 262144;
private static final int MAXWIDTH = 2000;
/**
* Method controls if a file exists.
*
* @param p path to the file
* @return boolean
*/
public static boolean control(Path p) {
return ((p != null) && Files.exists(p, LinkOption.NOFOLLOW_LINKS));
}
/**
* Method controls if a file exists and if it is a directory.
*
* @param p path to the directory
* @return boolean
*/
public static boolean controlDirectory(Path p) {
return ((p != null) && Files.exists(p, LinkOption.NOFOLLOW_LINKS) && Files.isDirectory(p, LinkOption.NOFOLLOW_LINKS));
}
/**
* Zips a directory and saves it at a given destination.
*
* @param dir the path to the directory that should be packed
* @param destDir the destination
* @param suffix the suffix of the new file
* @return boolean
* @throws IOException -
*/
public static boolean zipDirectoryTo(Path dir, Path destDir, String suffix) throws IOException {
if (!controlDirectory(dir) || !controlDirectory(destDir)) {
return false;
}
DirectoryZip.zipDirectory(dir, destDir, suffix);
return true;
}
/**
* Unpacks the zip to a given location.
*
* @param zip the zip file
* @param dir the destination directory
* @return boolean
* @throws IOException -
*/
public static boolean unzipDirectoryTo(Path zip, Path dir) throws IOException {
if (!control(zip) || !controlDirectory(dir)) {
return false;
}
return DirectoryZip.unpackZipTo(zip, dir);
}
/**
* Unpacks a single file from a zipfile.
*
* @param zip the zip file
* @param filename the name of the file in the zip
* @param destDirectory the destination directory
* @return boolean
* @throws IOException -
*/
public static boolean unzipFileFromZip(Path zip, String filename, Path destDirectory) throws IOException {
if (!control(zip)) {
return false;
}
return DirectoryZip.unpackFileFromZip(zip, filename, destDirectory);
}
/**
* Reads a textfile and returns a list with the lines.
*
* @param file The textfile
* @return the list of lines
*/
public static List<String> readTextFile(Path file) {
if (!FileUtil.control(file)) {
IllegalArgumentException iae = new IllegalArgumentException("The filepath is null or points to an invalid location!");
Main.handleUnhandableProblem(iae);
}
return FileReader.readFile(file);
}
/**
* Writes the list into a textfile. It is possible to add lines to an existing file.
*
* @param file the path to the textfile
* @param lines the lines to write
* @param append if the lines should be appended it the file exists.
* @return boolean
*/
public static boolean writeTextFile(Path file, List<String> lines, boolean append) {
if ((file == null) || Files.isDirectory(file, LinkOption.NOFOLLOW_LINKS)) {
return false;
}
return FileWriter.writeFile(file, lines, append);
}
/**
* Deletes a file.
*
* @param file the path to the file
* @return boolean
*/
public static boolean deleteFile(Path file) {
boolean ret = false;
if ((file != null) && Files.exists(file, LinkOption.NOFOLLOW_LINKS)) {
try {
if (file.toFile().canWrite()) {
Files.delete(file);
}
ret = !Files.exists(file, LinkOption.NOFOLLOW_LINKS);
} catch (IOException e) {
IllegalStateException ise = new IllegalStateException("An IO exception occured while deleting file '" + file + "'");
Main.handleUnhandableProblem(ise);
}
}
return ret;
}
/**
* Moves a file to a destination.
*
* @param file the path to the file to move
* @param destination the destination path
* @throws IOException thrown if a path is invalid
*/
public static void moveFile(Path file, Path destination) throws IOException {
if ((file == null) || !Files.exists(file, LinkOption.NOFOLLOW_LINKS) || (destination == null)) {
IllegalArgumentException iae = new IllegalArgumentException("The filepath is null or points to an invalid location! " + file);
Main.handleUnhandableProblem(iae);
}
Files.move(file, destination, StandardCopyOption.REPLACE_EXISTING);
}
/**
* Copies a file with or without its file attributes.
*
* @param file the file path
* @param destination the destination path
* @param withAttributs with or without file attributes
* @throws IOException if a path is invalid
*/
public static void copyFile(Path file, Path destination, boolean withAttributs) throws IOException {
if ((file == null) || !Files.exists(file, LinkOption.NOFOLLOW_LINKS) || (destination == null)) {
IllegalArgumentException iae = new IllegalArgumentException("The file is null or points to an invalid location!");
Main.handleUnhandableProblem(iae);
}
if (withAttributs) {
Files.copy(file, destination, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
} else {
Files.copy(file, destination, StandardCopyOption.REPLACE_EXISTING);
}
}
/**
* Creates a directory and if needed its parent directories.
*
* @param directory path of the directory
* @throws IOException -
*/
public static void createDirectory(Path directory) throws IOException {
if (directory == null) {
IllegalArgumentException iae = new IllegalArgumentException("The directorypath is null or points to an invalid location!");
Main.handleUnhandableProblem(iae);
}
Files.createDirectories(directory);
}
/**
* Deletes a directory.
*
* @param directory the path of the directory
* @throws IOException -
*/
public static void deleteDirectory(Path directory) throws IOException {
if (!FileUtil.controlDirectory(directory)) {
return;
}
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (file.toFile().canWrite()) {
Files.delete(file);
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
if (exc != null) {
Main.handleUnhandableProblem(exc);
}
if (dir.toFile().canWrite()) {
Files.delete(dir);
}
return FileVisitResult.CONTINUE;
}
});
}
/**
* Copies a directory to a destination.
*
* @param source the path to the source directory
* @param dest the path to the destination
* @throws IOException -
*/
public static void copyDirectory(Path source, final Path dest) throws IOException {
if ((source == null) || (dest == null) || !Files.exists(source, LinkOption.NOFOLLOW_LINKS)
|| !Files.isDirectory(source, LinkOption.NOFOLLOW_LINKS)) {
throw new InvalidParameterException();
}
Files.walkFileTree(source, new FileVisitor<Path>() {
Path tmp = dest;
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
this.tmp = this.tmp.resolve(dir.getFileName());
if (!Files.exists(this.tmp, LinkOption.NOFOLLOW_LINKS)) {
Files.createDirectory(this.tmp);
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (this.tmp.getFileName().equals(file.getParent().getFileName())) {
Files.copy(file, this.tmp.resolve(file.getFileName()), StandardCopyOption.REPLACE_EXISTING);
} else {
Files.copy(file, this.tmp.getParent().resolve(file.getFileName()), StandardCopyOption.REPLACE_EXISTING);
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
return FileVisitResult.TERMINATE;
}
});
}
/**
* Deactivates or resets the file protection of a windows file.
*
* @param file the path to the file
* @param activated boolean
* @return boolean
*/
public static boolean setProtection(Path file, boolean activated) {
boolean ret = false;
if (!FileUtil.control(file)) {
return ret;
}
if (activated) {
ret = WindowsFileProtection.resetProtection(file);
} else {
ret = WindowsFileProtection.removeProtection(file);
}
return ret;
}
/**
* Starts or ends the windows explorer.
*
* @param active boolean
* @return boolean
*/
public static boolean setWindowsExplorerActive(boolean active) {
boolean ret = false;
if (active) {
try {
ret = WindowsExplorer.start();
} catch (IOException
| InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
try {
ret = WindowsExplorer.shutdown();
} catch (IOException
| InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return ret;
}
/**
* Scales image to 256kb
*
* @param img Imagepath
* @throws IOException -
*/
public static void scaleImageTo256kb(Path img) throws IOException {
File imgFile = img.toFile();
if (imgFile.length() <= BYTE) {
return;
}
File newFile = Constants.PROGRAM_TMP_PATH.resolve(img.getFileName()).toFile();
BufferedImage i = ImageIO.read(imgFile);
if (i.getWidth() > MAXWIDTH) {
BufferedImage j = new BufferedImage(MAXWIDTH, (int) (i.getHeight() * ((float) MAXWIDTH / i.getWidth())), i.getType());
Graphics2D g2 = (Graphics2D) j.getGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2.drawImage(i, 0, 0, j.getWidth(), j.getHeight(), null);
ImageIO.write(j, "jpg", imgFile);
}
float quality = 1f;
float eps = 0.2f;
int c = 0;
Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName("jpeg");
ImageWriter writer = iter.next();
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
FileImageOutputStream output;
IIOImage image;
do {
c++;
FileUtil.deleteFile(newFile.toPath());
iwp.setCompressionQuality(quality);
output = new FileImageOutputStream(newFile);
writer.setOutput(output);
image = new IIOImage(ImageIO.read(imgFile), null, null);
writer.write(null, image, iwp);
writer.reset();
output.flush();
output.close();
quality -= eps / c;
} while ((newFile.length() > BYTE) && (quality > 0.1));
FileUtil.deleteFile(img);
FileUtil.moveFile(newFile.toPath(), img);
}
}