// Loosely based on the workaround posted here: // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4993360 // XXX why isn't this in Apache Commons? public static boolean isFileWritable(File file) { boolean isWritable = false; if (file != null) { boolean fileAlreadyExists = file.isFile(); // i.e. exists and is a File if (fileAlreadyExists || !file.exists()) { try { // true: open for append: make sure the open // doesn't clobber the file new FileOutputStream(file, true).close(); isWritable = true; if (!fileAlreadyExists) { // a new file has been "touch"ed; try to remove it try { if (!file.delete()) { LOGGER.warn("Can't delete temporary test file: {}", file.getAbsolutePath()); } } catch (SecurityException se) { LOGGER.error("Error deleting temporary test file: " + file.getAbsolutePath(), se); } } } catch (IOException | SecurityException ioe) { } } } return isWritable; }
/** * Detects charset/encoding for given file. Not 100% accurate for non-Unicode files. * * @param file File to detect charset/encoding * @return file's charset {@link org.mozilla.universalchardet.Constants} or null if not detected * @throws IOException */ public static String getFileCharset(File file) throws IOException { byte[] buf = new byte[4096]; final UniversalDetector universalDetector; try (BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file))) { universalDetector = new UniversalDetector(null); int numberOfBytesRead; while ((numberOfBytesRead = bufferedInputStream.read(buf)) > 0 && !universalDetector.isDone()) { universalDetector.handleData(buf, 0, numberOfBytesRead); } } universalDetector.dataEnd(); String encoding = universalDetector.getDetectedCharset(); if (encoding != null) { LOGGER.debug("Detected encoding for {} is {}.", file.getAbsolutePath(), encoding); } else { LOGGER.debug("No encoding detected for {}.", file.getAbsolutePath()); } universalDetector.reset(); return encoding; }
public static File getFileNameWithAddedExtension(File parent, File f, String ext) { File ff = new File(parent, f.getName() + ext); if (ff.exists()) { return ff; } return null; }
/** * Converts UTF-16 inputFile to UTF-8 outputFile. Does not overwrite existing outputFile file. * * @param inputFile UTF-16 file * @param outputFile UTF-8 file after conversion * @throws IOException */ public static void convertFileFromUtf16ToUtf8(File inputFile, File outputFile) throws IOException { String charset; if (inputFile == null || !inputFile.canRead()) { throw new FileNotFoundException("Can't read inputFile."); } try { charset = getFileCharset(inputFile); } catch (IOException ex) { LOGGER.debug("Exception during charset detection.", ex); throw new IllegalArgumentException("Can't confirm inputFile is UTF-16."); } if (isCharsetUTF16(charset)) { if (!outputFile.exists()) { BufferedReader reader = null; try { if (equalsIgnoreCase(charset, CHARSET_UTF_16LE)) { reader = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile), "UTF-16")); } else { reader = new BufferedReader( new InputStreamReader(new FileInputStream(inputFile), "UTF-16BE")); } } catch (UnsupportedEncodingException ex) { LOGGER.warn("Unsupported exception.", ex); throw ex; } BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile), "UTF-8")); int c; while ((c = reader.read()) != -1) { writer.write(c); } writer.close(); reader.close(); } } else { throw new IllegalArgumentException("File is not UTF-16"); } }
public static boolean isSubtitlesExists(File file, DLNAMediaInfo media, boolean usecache) { boolean found = false; if (file.exists()) { found = browseFolderForSubtitles(file.getParentFile(), file, media, usecache); } String alternate = PMS.getConfiguration().getAlternateSubtitlesFolder(); if (isNotBlank(alternate)) { // https://code.google.com/p/ps3mediaserver/issues/detail?id=737#c5 File subFolder = new File(alternate); if (!subFolder.isAbsolute()) { subFolder = new File(file.getParent() + "/" + alternate); try { subFolder = subFolder.getCanonicalFile(); } catch (IOException e) { LOGGER.debug("Caught exception", e); } } if (subFolder.exists()) { found = found || browseFolderForSubtitles(subFolder, file, media, usecache); } } return found; }
public static boolean isFolderRelevant( File f, PmsConfiguration configuration, Set<String> ignoreFiles) { if (f.isDirectory() && configuration.isHideEmptyFolders()) { File[] children = f.listFiles(); /** * listFiles() returns null if "this abstract pathname does not denote a directory, or if an * I/O error occurs". in this case (since we've already confirmed that it's a directory), this * seems to mean the directory is non-readable * http://www.ps3mediaserver.org/forum/viewtopic.php?f=6&t=15135 * http://stackoverflow.com/questions/3228147/retrieving-the-underlying-error-when-file-listfiles-return-null */ if (children == null) { LOGGER.warn("Can't list files in non-readable directory: {}", f.getAbsolutePath()); } else { for (File child : children) { if (ignoreFiles.contains(child.getAbsolutePath())) { continue; } if (child.isFile()) { if (FormatFactory.getAssociatedFormat(child.getName()) != null || isFileRelevant(child, configuration)) { return true; } } else { if (isFolderRelevant(child, configuration, ignoreFiles)) { return true; } } } } } return false; }
// XXX dir.canRead() has issues on Windows, so verify it directly: // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6203387 public static boolean isDirectoryReadable(File dir) { boolean isReadable = false; if (dir != null) { // new File("").isDirectory() is false, even though getAbsolutePath() returns the right path. // this resolves it dir = dir.getAbsoluteFile(); if (dir.isDirectory()) { try { File[] files = dir.listFiles(); // null if an I/O error occurs isReadable = files != null; } catch (SecurityException se) { } } } return isReadable; }
public static File isFileExists(File f, String ext) { int point = f.getName().lastIndexOf('.'); if (point == -1) { point = f.getName().length(); } File lowerCasedFile = new File(f.getParentFile(), f.getName().substring(0, point) + "." + ext.toLowerCase()); if (lowerCasedFile.exists()) { return lowerCasedFile; } File upperCasedFile = new File(f.getParentFile(), f.getName().substring(0, point) + "." + ext.toUpperCase()); if (upperCasedFile.exists()) { return upperCasedFile; } return null; }
// XXX dir.canWrite() has issues on Windows, so verify it directly: // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6203387 public static boolean isDirectoryWritable(File dir) { boolean isWritable = false; if (dir != null) { // new File("").isDirectory() is false, even though getAbsolutePath() returns the right path. // this resolves it dir = dir.getAbsoluteFile(); if (dir.isDirectory()) { File file = new File( dir, String.format( "pms_directory_write_test_%d_%d.tmp", System.currentTimeMillis(), Thread.currentThread().getId())); try { if (file.createNewFile()) { if (isFileWritable(file)) { isWritable = true; } if (!file.delete()) { LOGGER.warn("Can't delete temporary test file: {}", file.getAbsolutePath()); } } } catch (IOException | SecurityException ioe) { } } } return isWritable; }
// based on the workaround posted here: // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4993360 // XXX why isn't this in Apache Commons? public static boolean isFileReadable(File file) { boolean isReadable = false; if ((file != null) && file.isFile()) { try { new FileInputStream(file).close(); isReadable = true; } catch (IOException ioe) { } } return isReadable; }
public static boolean isFileRelevant(File f, PmsConfiguration configuration) { String fileName = f.getName().toLowerCase(); if ((configuration.isArchiveBrowsing() && (fileName.endsWith(".zip") || fileName.endsWith(".cbz") || fileName.endsWith(".rar") || fileName.endsWith(".cbr"))) || fileName.endsWith(".iso") || fileName.endsWith(".img") || fileName.endsWith(".m3u") || fileName.endsWith(".m3u8") || fileName.endsWith(".pls") || fileName.endsWith(".cue")) { return true; } return false; }
// this is called from a static initialiser, where errors aren't clearly reported, // so do everything possible to return a valid reponse, even if the parameters // aren't sane public static FileLocation getFileLocation( String customPath, String defaultDirectory, String defaultBasename) { File customFile = null; File directory = null; File file = null; if (isBlank(defaultBasename)) { // shouldn't get here defaultBasename = DEFAULT_BASENAME; } if (defaultDirectory == null) { defaultDirectory = ""; // current directory } if (customPath != null) { customFile = new File(customPath).getAbsoluteFile(); } if (customFile != null) { if (customFile.exists()) { if (customFile.isDirectory()) { directory = customFile; file = new File(customFile, defaultBasename).getAbsoluteFile(); } else { directory = customFile.getParentFile(); file = customFile; } } else { File parentDirectoryFile = customFile.getParentFile(); if (parentDirectoryFile != null && parentDirectoryFile.exists()) { // parent directory exists: the file can be created directory = parentDirectoryFile; file = customFile; } } } if (directory == null || file == null) { directory = new File(defaultDirectory).getAbsoluteFile(); file = new File(directory, defaultBasename).getAbsoluteFile(); } return new FileLocation(directory, file); }
private static synchronized boolean browseFolderForSubtitles( File subFolder, File file, DLNAMediaInfo media, boolean usecache) { boolean found = false; if (!usecache) { cache = null; } if (cache == null) { cache = new HashMap<>(); } final Set<String> supported = SubtitleType.getSupportedFileExtensions(); File[] allSubs = cache.get(subFolder); if (allSubs == null) { allSubs = subFolder.listFiles( new FilenameFilter() { @Override public boolean accept(File dir, String name) { String ext = FilenameUtils.getExtension(name).toLowerCase(); if ("sub".equals(ext)) { // Avoid microdvd/vobsub confusion by ignoring sub+idx pairs here since // they'll come in unambiguously as vobsub via the idx file anyway return isFileExists(new File(dir, name), "idx") == null; } return supported.contains(ext); } }); if (allSubs != null) { cache.put(subFolder, allSubs); } } String fileName = getFileNameWithoutExtension(file.getName()).toLowerCase(); if (allSubs != null) { for (File f : allSubs) { if (f.isFile() && !f.isHidden()) { String fName = f.getName().toLowerCase(); for (String ext : supported) { if (fName.length() > ext.length() && fName.startsWith(fileName) && endsWithIgnoreCase(fName, "." + ext)) { int a = fileName.length(); int b = fName.length() - ext.length() - 1; String code = ""; if (a <= b) { // handling case with several dots: <video>..<extension> code = fName.substring(a, b); } if (code.startsWith(".")) { code = code.substring(1); } boolean exists = false; if (media != null) { for (DLNAMediaSubtitle sub : media.getSubtitleTracksList()) { if (f.equals(sub.getExternalFile())) { exists = true; } else if (equalsIgnoreCase(ext, "idx") && sub.getType() == SubtitleType.MICRODVD) { // sub+idx => VOBSUB sub.setType(SubtitleType.VOBSUB); exists = true; } else if (equalsIgnoreCase(ext, "sub") && sub.getType() == SubtitleType.VOBSUB) { // VOBSUB try { sub.setExternalFile(f); } catch (FileNotFoundException ex) { LOGGER.warn("Exception during external subtitles scan.", ex); } exists = true; } } } if (!exists) { DLNAMediaSubtitle sub = new DLNAMediaSubtitle(); sub.setId( 100 + (media == null ? 0 : media.getSubtitleTracksList().size())); // fake id, not used if (code.length() == 0 || !Iso639.getCodeList().contains(code)) { sub.setLang(DLNAMediaSubtitle.UND); sub.setType(SubtitleType.valueOfFileExtension(ext)); if (code.length() > 0) { sub.setFlavor(code); if (sub.getFlavor().contains("-")) { String flavorLang = sub.getFlavor().substring(0, sub.getFlavor().indexOf('-')); String flavorTitle = sub.getFlavor().substring(sub.getFlavor().indexOf('-') + 1); if (Iso639.getCodeList().contains(flavorLang)) { sub.setLang(flavorLang); sub.setFlavor(flavorTitle); } } } } else { sub.setLang(code); sub.setType(SubtitleType.valueOfFileExtension(ext)); } try { sub.setExternalFile(f); } catch (FileNotFoundException ex) { LOGGER.warn("Exception during external subtitles scan.", ex); } found = true; if (media != null) { media.getSubtitleTracksList().add(sub); } } } } } } } return found; }
public static File getFileNameWithNewExtension(File parent, File file, String ext) { return isFileExists(new File(parent, file.getName()), ext); }
FileLocation(File directory, File file) { this.directoryPath = FilenameUtils.normalize(directory.getAbsolutePath()); this.filePath = FilenameUtils.normalize(file.getAbsolutePath()); }