EpicKnarvik97 2c75d91cce
All checks were successful
KnarCraft/FFmpegConvert/pipeline/head This commit looks good
Adds a converter to embed subtitles
2024-03-27 12:36:11 +01:00

185 lines
6.7 KiB
Java

package net.knarcraft.ffmpegconverter.utility;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* A class which helps with file handling
*/
public final class FileUtil {
private FileUtil() {
}
/**
* Gets the path described by the input, but changed to account for collisions
*
* @param folder <p>The folder containing the output file.</p>
* @param file <p>The input file.</p>
* @param outExtension <p>The extension of the output file.</p>
* @return <p>A file name with the new extension and without any collisions.</p>
*/
public static String getNonCollidingPath(File folder, File file, String outExtension) {
return FileUtil.getNonCollidingFilename(folder.getAbsolutePath() + File.separator +
FileUtil.stripExtension(file.getName()) + "." + outExtension, outExtension);
}
/**
* Recursively lists all files in a folder
*
* @param folder <p>The folder to start from.</p>
* @param maxRecursions <p>Maximum number of recursions</p>
* @return A list of files
*/
public static File[] listFilesRecursive(File folder, String[] extensions, int maxRecursions) {
//Return if the target depth has been reached
if (maxRecursions == 0) {
return null;
}
//Get a list of all files which are folders and has one of the extensions specified
File[] foundFiles = folder.listFiles((file) -> file.isFile() &&
ListUtil.listContains(extensions, (item) -> file.getName().toLowerCase().endsWith(item)));
//Return if recursion is finished
if (maxRecursions == 1) {
return foundFiles;
}
//Get all folders in the directory
File[] subFolders = folder.listFiles((dir, name) -> new File(dir, name).isDirectory());
//Return if the folder has no sub folders
if (subFolders == null) {
return foundFiles;
}
for (File subFolder : subFolders) {
//Get all relevant files contained within the sub folder
File[] nextLevel = listFilesRecursive(subFolder, extensions, maxRecursions - 1);
//Add found files to the output
if (nextLevel != null) {
if (foundFiles == null) {
foundFiles = nextLevel;
} else {
foundFiles = ListUtil.concatenate(foundFiles, nextLevel);
}
}
}
return foundFiles;
}
/**
* Reads a file's contents to a string list
*
* <p>The file must contain the number of lines to read in the first line.</p>
*
* @param fileName <p>The file to read.</p>
* @return <p>A string list where each element is one line of the file.</p>
* @throws IOException <p>If the file cannot be read.</p>
*/
public static String[] readFileLines(String fileName) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(getResourceAsStream(fileName)));
int numberOfLines = Integer.parseInt(reader.readLine());
String[] lines = new String[numberOfLines];
for (int i = 0; i < lines.length; i++) {
lines[i] = reader.readLine();
}
return lines;
}
/**
* Gets a resource as an InputStream
*
* @param resourceName <p>The name of the resource you want to read.</p>
* @return <p>An input stream which can be used to access the resource.</p>
*/
private static InputStream getResourceAsStream(String resourceName) {
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
return classloader.getResourceAsStream(resourceName);
}
/**
* Adds parentheses with an integer if the output file already exists
*
* @param targetPath <p>The path the file should ideally be saved at.</p>
* @param extension <p>The extension of the target file.</p>
* @return <p>A filename guaranteed not to collide with other files.</p>
*/
private static String getNonCollidingFilename(String targetPath, String extension) {
File newFile = new File(targetPath);
String fileName = stripExtension(targetPath).replaceAll("\\([0-9]+\\)$", "");
int i = 1;
while (newFile.exists()) {
newFile = new File(fileName + "(" + i++ + ")" + "." + extension);
}
return newFile.toString();
}
/**
* Gets the extension of the given filename
*
* @param file <p>The filename to check</p>
* @return <p>The file's extension</p>
*/
public static String getExtension(String file) {
if (file.contains(".")) {
return file.substring(file.lastIndexOf('.') + 1);
} else {
return "";
}
}
/**
* Removes the extension from a file name
*
* @param file <p>A filename.</p>
* @return <p>A filename without its extension.</p>
*/
public static String stripExtension(String file) {
return file.substring(0, file.lastIndexOf('.'));
}
/**
* Gets the locale specifying the language of the given file name
*
* @param fileName <p>The file name to check</p>
* @return <p>The locale, or null if no locale could be parsed</p>
*/
public static @Nullable String getLanguage(@NotNull String fileName) {
fileName = stripExtension(fileName);
String possibleLanguage = getExtension(fileName);
// NRK Nett-TV has a tendency to use nb-ttv for Norwegian for some reason
possibleLanguage = possibleLanguage.replace("nb-ttv", "nb-nor");
// TODO: Some languages are specified by using "-en" or "-English" or ".en" or ".English" at the end of file names
if (possibleLanguage.length() <= 1 || (possibleLanguage.length() >= 4 &&
(!possibleLanguage.contains("-") || possibleLanguage.length() >= 8))) {
return null;
}
// Hope the text is an actual valid language
if (!possibleLanguage.contains("-")) {
return possibleLanguage;
}
// Make sure the "-" has at least two characters on each side
String[] parts = possibleLanguage.split("-");
if (parts[0].length() < 2 || parts[1].length() < 2) {
return null;
}
if (parts[1].length() == 3) {
// Return three-letter country code
return parts[1].toLowerCase();
} else {
// Return en-US country code
return parts[0].substring(0, 2).toLowerCase() + "-" + parts[1].substring(0, 2).toUpperCase();
}
}
}