📄 fileutil.java
字号:
/*
* Created on Oct 10, 2003
* Modified Apr 14, 2004 by Alon Rohter
* Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package org.gudy.azureus2.core3.util;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
import org.gudy.azureus2.platform.PlatformManager;
import org.gudy.azureus2.platform.PlatformManagerFactory;
import org.gudy.azureus2.platform.PlatformManagerCapabilities;
import org.gudy.azureus2.plugins.platform.PlatformManagerException;
import java.io.*;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* File utility class.
*/
public class FileUtil {
private static final LogIDs LOGID = LogIDs.CORE;
public static final String DIR_SEP = System.getProperty("file.separator");
private static final int RESERVED_FILE_HANDLE_COUNT = 4;
private static List reserved_file_handles = new ArrayList();
private static AEMonitor class_mon = new AEMonitor( "FileUtil:class" );
public static String getCanonicalFileName(String filename) {
// Sometimes Windows use filename in 8.3 form and cannot
// match .torrent extension. To solve this, canonical path
// is used to get back the long form
String canonicalFileName = filename;
try {
canonicalFileName = new File(filename).getCanonicalPath();
}
catch (IOException ignore) {}
return canonicalFileName;
}
public static File getUserFile(String filename) {
return new File(SystemProperties.getUserPath(), filename);
}
public static File getApplicationFile(String filename) {
String path = SystemProperties.getApplicationPath();
if(Constants.isOSX) {
path = path + "/" + SystemProperties.getApplicationName() + ".app/Contents/";
}
return new File(path, filename);
}
public static boolean isTorrentFile(String filename) throws FileNotFoundException, IOException {
File check = new File(filename);
if (!check.exists())
throw new FileNotFoundException("File "+filename+" not found.");
if (!check.canRead())
throw new IOException("File "+filename+" cannot be read.");
if (check.isDirectory())
throw new FileIsADirectoryException("File "+filename+" is a directory.");
try {
TOTorrentFactory.deserialiseFromBEncodedFile(check);
return true;
} catch (Throwable e) {
return false;
}
}
/**
* Deletes the given dir and all files/dirs underneath
*/
public static void recursiveDelete(File f) {
String defSaveDir = COConfigurationManager.getStringParameter("Default save path", "");
String moveToDir = COConfigurationManager.getStringParameter("Completed Files Directory", "");
try{
moveToDir = new File(moveToDir).getCanonicalPath();
}catch( Throwable e ){
}
try{
defSaveDir = new File(defSaveDir).getCanonicalPath();
}catch( Throwable e ){
}
try {
if (f.getCanonicalPath().equals(moveToDir)) {
System.out.println("FileUtil::recursiveDelete:: not allowed to delete the MoveTo dir !");
return;
}
if (f.getCanonicalPath().equals(defSaveDir)) {
System.out.println("FileUtil::recursiveDelete:: not allowed to delete the default data dir !");
return;
}
if (f.isDirectory()) {
File[] files = f.listFiles();
for (int i = 0; i < files.length; i++) {
recursiveDelete(files[i]);
}
f.delete();
}
else {
f.delete();
}
} catch (Exception ignore) {/*ignore*/}
}
public static long
getFileOrDirectorySize(
File file )
{
if ( file.isFile()){
return( file.length());
}else{
long res = 0;
File[] files = file.listFiles();
if ( files != null ){
for (int i=0;i<files.length;i++){
res += getFileOrDirectorySize( files[i] );
}
}
return( res );
}
}
/**
* Deletes the given dir and all dirs underneath if empty.
* Don't delete default save path or completed files directory, however,
* allow deletion of their empty subdirectories
* Files defined to be ignored for the sake of torrent creation are automatically deleted
* For example, by default this includes thumbs.db
*/
public static void
recursiveEmptyDirDelete(
File f)
{
recursiveEmptyDirDelete( f, true );
}
public static void
recursiveEmptyDirDelete(
File f,
boolean log_warnings )
{
Set ignore_map = TorrentUtils.getIgnoreSet();
recursiveEmptyDirDelete( f, ignore_map, log_warnings );
}
private static void
recursiveEmptyDirDelete(
File f,
Set ignore_set,
boolean log_warnings )
{
try {
String defSaveDir = COConfigurationManager.getStringParameter("Default save path", "");
String moveToDir = COConfigurationManager.getStringParameter("Completed Files Directory", "");
if ( defSaveDir.trim().length() > 0 ){
defSaveDir = new File(defSaveDir).getCanonicalPath();
}
if ( moveToDir.trim().length() > 0 ){
moveToDir = new File(moveToDir).getCanonicalPath();
}
if ( f.isDirectory()){
File[] files = f.listFiles();
if ( files == null ){
if (log_warnings ){
Debug.out("Empty folder delete: failed to list contents of directory " + f );
}
return;
}
for (int i = 0; i < files.length; i++) {
File x = files[i];
if ( x.isDirectory()){
recursiveEmptyDirDelete(files[i],ignore_set,log_warnings);
}else{
if ( ignore_set.contains( x.getName().toLowerCase())){
if ( !x.delete()){
if ( log_warnings ){
Debug.out("Empty folder delete: failed to delete file " + x );
}
}
}
}
}
if (f.getCanonicalPath().equals(moveToDir)) {
if ( log_warnings ){
Debug.out("Empty folder delete: not allowed to delete the MoveTo dir !");
}
return;
}
if (f.getCanonicalPath().equals(defSaveDir)) {
if ( log_warnings ){
Debug.out("Empty folder delete: not allowed to delete the default data dir !");
}
return;
}
if (f.listFiles().length == 0) {
if ( !f.delete()){
if ( log_warnings ){
Debug.out("Empty folder delete: failed to delete directory " + f );
}
}
}else{
if ( log_warnings ){
Debug.out("Empty folder delete: "+f.listFiles().length+" file(s)/folder(s) still in " + f + ". Not removing.");
}
}
}
} catch (Exception e) { Debug.out(e.toString()); }
}
public static String
convertOSSpecificChars(
String file_name_in )
{
// this rule originally from DiskManager
char[] chars = file_name_in.toCharArray();
for (int i=0;i<chars.length;i++){
if ( chars[i] == '"' ){
chars[i] = '\'';
}
}
if ( !Constants.isOSX ){
if ( Constants.isWindows ){
// this rule originally from DiskManager
for (int i=0;i<chars.length;i++){
char c = chars[i];
if ( c == '\\' || c == '/' || c == ':' || c == '?' || c == '*' ){
chars[i] = '_';
}
}
}
// '/' is valid in mac file names, replace with space
// so it seems are cr/lf
for (int i=0;i<chars.length;i++){
char c = chars[i];
if ( c == '/' || c == '\r' || c == '\n' ){
chars[i] = ' ';
}
}
}
String file_name_out = new String(chars);
try{
// mac file names can end in space - fix this up by getting
// the canonical form which removes this on Windows
String str = new File(file_name_out).getCanonicalFile().toString();
int p = str.lastIndexOf( File.separator );
file_name_out = str.substring(p+1);
}catch( Throwable e ){
// ho hum, carry on, it'll fail later
//e.printStackTrace();
}
//System.out.println( "convertOSSpecificChars: " + file_name_in + " ->" + file_name_out );
return( file_name_out );
}
public static void
writeResilientConfigFile(
String file_name,
Map data )
{
File parent_dir = new File(SystemProperties.getUserPath());
boolean use_backups = COConfigurationManager.getBooleanParameter("Use Config File Backups" );
writeResilientFile( parent_dir, file_name, data, use_backups );
}
public static void
writeResilientFile(
File file,
Map data )
{
writeResilientFile( file.getParentFile(), file.getName(), data, false );
}
public static void
writeResilientFile(
File parent_dir,
String file_name,
Map data,
boolean use_backup )
{
if ( use_backup ){
File originator = new File( parent_dir, file_name );
if ( originator.exists()){
backupFile( originator, true );
}
}
writeResilientFile( parent_dir, file_name, data );
}
// synchronise it to prevent concurrent attempts to write the same file
private static void
writeResilientFile(
File parent_dir,
String file_name,
Map data )
{
try{
class_mon.enter();
try{
getReservedFileHandles();
File temp = new File( parent_dir, file_name + ".saving");
BufferedOutputStream baos = null;
try{
byte[] encoded_data = BEncoder.encode(data);
baos = new BufferedOutputStream( new FileOutputStream( temp, false ), 8192 );
baos.write( encoded_data );
baos.flush();
baos.close();
baos = null;
//only use newly saved file if it got this far, i.e. it saved successfully
if ( temp.length() > 1L ) {
File file = new File( parent_dir, file_name );
if ( file.exists() ){
file.delete();
}
temp.renameTo( file );
}
}catch (Exception e) {
Logger.log(new LogAlert(LogAlert.UNREPEATABLE, "Save of '"
+ file_name + "' fails", e));
}finally{
try {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -