fileutil.java

来自「Azureus is a powerful, full-featured, cr」· Java 代码 · 共 912 行 · 第 1/2 页

JAVA
912
字号
 /*
 * Created on Oct 10, 2003
 * Modified Apr 14, 2004 by Alon Rohter
 * Copyright (C) 2004 Aelitis, All Rights Reserved.
 * 
 */

package org.gudy.azureus2.core3.util;

import java.io.*;
import java.net.URI;
import java.util.*;

import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
import org.gudy.azureus2.core3.config.*;
import org.gudy.azureus2.core3.logging.*;

/**
 * File utility class.
 */
public class FileUtil {
  
  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 + "/Azureus.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 {
      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) 
  {  
    Map		ignore_map	= new HashMap();
    
	String	ignore_list = COConfigurationManager.getStringParameter( "File.Torrent.IgnoreFiles", TOTorrent.DEFAULT_IGNORE_FILES );
	
	int	pos = 0;
	
	while(true){
		
		int	p1 = ignore_list.indexOf( ";", pos );
		
		String	bit;
		
		if ( p1 == -1 ){
			
			bit = ignore_list.substring(pos);
			
		}else{
			
			bit	= ignore_list.substring( pos, p1 );
			
			pos	= p1+1;
		}
		
		ignore_map.put(bit.trim().toLowerCase(),"");
		
		if ( p1 == -1 ){
			
			break;
		}
	}
	
	recursiveEmptyDirDelete( f, ignore_map );
  }
  
  private static void 
  recursiveEmptyDirDelete(
  	File f,
	Map	ignore_map ) 
  {
     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 ){
        	
          	Debug.out("FileUtil::recursiveEmptyDirDelete:: failed 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_map);
        		
        	}else{
        		
        		if ( ignore_map.get( x.getName().toLowerCase()) != null ){
        			
        			if ( !x.delete()){
        				
        	          	Debug.out("FileUtil::recursiveEmptyDirDelete:: failed to delete file" + x );
        			}
        		}
        	}
        }

        if (f.getCanonicalPath().equals(moveToDir)) {
        	
          Debug.out("FileUtil::recursiveEmptyDirDelete:: not allowed to delete the MoveTo dir !");
          
          return;
        }
        
        if (f.getCanonicalPath().equals(defSaveDir)) {
        	
          Debug.out("FileUtil::recursiveEmptyDirDelete:: not allowed to delete the default data dir !");
          
          return;
        }

        if (f.listFiles().length == 0) {
        	
          if ( !f.delete()){
          	
           	Debug.out("FileUtil::recursiveEmptyDirDelete:: failed to delete directory" + f );
         	
          }
        }else{
        	Debug.out("FileUtil::recursiveEmptyDirDelete:: "+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 );
  }
  
  	// synchronise it to prevent concurrent attempts to write the same file
  
  public static void
  writeResilientConfigFile(
  	String		file_name,
	Map			data )
  {
  	try{
  		class_mon.enter();
  	
	  	try{
	  		getReservedFileHandles();
	      File temp = new File( SystemProperties.getUserPath() + 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( SystemProperties.getUserPath() + file_name );
	        	if ( file.exists() ){
	        		file.delete();
	        	}
	        	temp.renameTo( file );
	        }
	
		    }catch (Exception e) {
		    
		    	LGLogger.logUnrepeatableAlert( "Save of '" + file_name + "' fails", e );
		    	
		    }finally{
		    	
		    	try {
		    		if (baos != null){
		    			
		    			baos.close();
		    		}
		    	}catch( Exception e){
		    		
		        	LGLogger.logUnrepeatableAlert( "Save of '" + file_name + "' fails", e ); 
		    	}
		    }
	  	}finally{
	  		
	  		releaseReservedFileHandles();
	  	}
  	}finally{
  		
  		class_mon.exit();
  	}
  }
  
  	// synchronised against writes to make sure we get a consistent view
  
  	public static Map
	readResilientConfigFile(
		String		file_name )
	{
  		try{
  			class_mon.enter();
	  	
	  		try{
	  			getReservedFileHandles();
	  	
	  			return(readResilientConfigFile( file_name, 0 ));
	  			
	  		}catch( Throwable e ){
	  			
	  				// just in case something went wrong, make sure we just return a blank
	  				// map
	  			
	  			Debug.printStackTrace( e );
	  			
	  			return( new HashMap());
	  			
	  		}finally{
	  			
	  			releaseReservedFileHandles();
	  		}
  		}finally{
  			
  			class_mon.exit();
  		}
  	}
  	
	private static Map
	readResilientConfigFile(
		String		file_name,
		int			fail_count )
	{	  
  			// open the file
  	
  		boolean	using_backup	= file_name.endsWith(".saving");
  		
  		File file = new File( SystemProperties.getUserPath() + file_name );
	    
	   		//make sure the file exists and isn't zero-length
	    
  		if ( (!file.exists()) || file.length() <= 1L ){

  			if ( using_backup ){
	     
  				if ( fail_count == 1 ){
  					
  						// we only alert the user if at least one file was found and failed
  						// otherwise it could be start of day when neither file exists yet
  					
  					LGLogger.logUnrepeatableAlert( 	LGLogger.AT_ERROR,
  										"Load of '" + file_name + "' fails, no usable file or backup" );
  				}else{
  					
  					LGLogger.log( 	LGLogger.INFORMATION,
									"Load of '" + file_name + "' fails, file not found" );
				
  				}
	       
  				return( new HashMap());
  			}
        
  			LGLogger.log("Load of '" + file_name + "' failed, file not found or 0-sized." );

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?