⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fileutil.java

📁 这是一个基于java编写的torrent的P2P源码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
						"Backup file '" + backup_file
								+ "' has been used for recovery purposes"));
				
					// rewrite the good data, don't use backups here as we want to
					// leave the original backup in place for the moment
				
				writeResilientFile( parent_dir, file_name, res, false );
				
	 		}else{
	 			
	 				// neither main nor backup file ok, retry main file with recovery
	 			
	 			res = readResilientFileSupport( parent_dir, file_name, true );
	 		}
 		}
 		
 		if ( res == null ){
 			
 			res = new HashMap();
 		}
 		
 		return( res );
 	}

  		// synchronised against writes to make sure we get a consistent view
  
  	private static Map
	readResilientFileSupport(
		File		parent_dir,
		String		file_name,
		boolean		attempt_recovery )
	{
   		try{
  			class_mon.enter();
	  	
	  		try{
	  			getReservedFileHandles();
	  	
	  			Map	res = null;
	  			
	  			try{
	  				res = readResilientFile( parent_dir, file_name, 0, false );
	  			
	  			}catch( Throwable e ){
	  				
	  				// ignore, it'll be rethrown if we can't recover below
	  			}
	  			
	  			if ( res == null && attempt_recovery ){
	  				
	  				res = readResilientFile( parent_dir, file_name, 0, true );
	  				
	  				if ( res != null ){
	  					Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_WARNING,
								"File '" + file_name + "' has been partially recovered, "
										+ "information may have been lost!"));
	  				}
	  			}
	  			
	  			return( res );
	  			
	  		}catch( Throwable e ){
	  				  			
	  			Debug.printStackTrace( e );
	  			
	  			return( null );
	  			
	  		}finally{
	  			
	  			releaseReservedFileHandles();
	  		}
  		}finally{
  			
  			class_mon.exit();
  		}
  	}
  	
	private static Map
	readResilientFile(
		File		parent_dir,
		String		file_name,
		int			fail_count,
		boolean		recovery_mode )
	{	  
			// logging in here is only done during "non-recovery" mode to prevent subsequent recovery
			// attempts logging everything a second time.
			// recovery-mode allows the decoding process to "succeed" with a partially recovered file
		
  		boolean	using_backup	= file_name.endsWith(".saving");
  		
  		File file = new File(  parent_dir, file_name );
	    
	   		//make sure the file exists and isn't zero-length
	    
  		if ( (!file.exists()) || file.length() <= 1L ){

  			if ( using_backup ){
	     
  				if ( !recovery_mode ){
  					
	  				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
	  					Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR,
								"Load of '" + file_name + "' fails, no usable file or backup"));
	  				}else{
	  					// drop this log, it doesn't really help to inform about the failure to 
	  					// find a .saving file
	  					
	  					//if (Logger.isEnabled())
						//		Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "Load of '"
						//				+ file_name + "' fails, file not found"));
					
	  				}
  				}
	       
  				return( null );
  			}
        
  			if ( !recovery_mode ){
  				
  				// kinda confusing log this as we get it under "normal" circumstances (loading a config
  				// file that doesn't exist legitimately, e.g. shares or bad-ips
//  				if (Logger.isEnabled())
//						Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "Load of '"
//								+ file_name + "' failed, " + "file not found or 0-sized."));
  			}
  			
  			return( readResilientFile( parent_dir, file_name + ".saving", 0, recovery_mode ));
  		}

  		BufferedInputStream bin = null;
   
  		try{
  			int	retry_limit = 5;
  			
  			while(true){
  				
  				try{
  					bin = new BufferedInputStream( new FileInputStream(file), 16384 );
  				
  					break;
  					
  				}catch( IOException e ){
  				
  	 				if ( --retry_limit == 0 ){
  						
  						throw( e );
  					}
  	 				
  	 				if (Logger.isEnabled())
							Logger.log(new LogEvent(LOGID, "Failed to open '" + file.toString()
								+ "', retrying", e));
  					
  					Thread.sleep(500);
  				}
  			}
  			
  			BDecoder	decoder = new BDecoder();
  			
  			if ( recovery_mode ){
  				
  				decoder.setRecoveryMode( true );
  			}
  			
	    	Map	res = decoder.decodeStream(bin);
	    	
	    	if ( using_backup && !recovery_mode ){
  		
	    		Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_WARNING,
						"Load of '" + file_name.substring(0, file_name.length() - 7)
								+ "' had to revert to backup file")); 
	    	}
	    	
	    	return( res );
	    	
	    }catch( Throwable e ){
	    	
	    	Debug.printStackTrace( e );
	    	
	    	try {  
	    		if (bin != null){
	    			
	    			bin.close();
	    			
	    			bin	= null;
	    		}
	    	} catch (Exception x) { 
	    		
	    		Debug.printStackTrace( x ); 
	    	}
	    	
	    		// if we're not recovering then backup the file
	    	
	    	if ( !recovery_mode ){
	    		
	   			// Occurs when file is there but b0rked
      			// copy it in case it actually contains useful data, so it won't be overwritten next save
    	
		    	File bad;
		    	
		    	int	bad_id = 0;
		    	
		    	while(true){
		    		
		    		File	test = new File( parent_dir, file.getName() + ".bad" + (bad_id==0?"":(""+bad_id)));
		    		
		    		if ( !test.exists()){
		    			
		    			bad	= test;
		    			
		    			break;
		    		}
		    		
		    		bad_id++;
		    	}

		    	if (Logger.isEnabled())
						Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING, "Read of '"
								+ file_name + "' failed, decoding error. " + "Renaming to "
								+ bad.getName()));
	
		    		// copy it so its left in place for possible recovery
		    	
		    	copyFile( file, bad );
	    	}
	    	
	    	if ( using_backup ){
		
	    		if ( !recovery_mode ){
	    			Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR,
							"Load of '" + file_name + "' fails, no usable file or backup")); 
	    		}
	    			
	    		return( null );
	    	}
	    	
	    	return( readResilientFile( parent_dir, file_name + ".saving", 1, recovery_mode ));
 			 
	    }finally{
	    	
	    	try {
	    		
	    		if (bin != null){
	    			
	    			bin.close();
	    		}
	    	}catch (Exception e) {
	    		
	    		Debug.printStackTrace( e );
	    	}
	    }
	}
  

	private static void
	getReservedFileHandles()
	{
		try{
			class_mon.enter();
		
			while( reserved_file_handles.size() > 0 ){
				
				// System.out.println( "releasing reserved file handle");
				
				InputStream	is = (InputStream)reserved_file_handles.remove(0);
				
				try{
					is.close();
					
				}catch( Throwable e ){
					
					Debug.printStackTrace( e );
				}
			}
		}finally{
			
			class_mon.exit();
		}
	}
			
	private static void
	releaseReservedFileHandles()
	{
		try{
			
			class_mon.enter();
			
			File	lock_file	= new File(SystemProperties.getUserPath() + ".lock");
							
			lock_file.createNewFile();
		
			while(  reserved_file_handles.size() < RESERVED_FILE_HANDLE_COUNT ){
				
				// System.out.println( "getting reserved file handle");
				
				InputStream	is = new FileInputStream( lock_file );
				
				reserved_file_handles.add(is);
			}
		}catch( Throwable e ){
		
			Debug.printStackTrace( e );
			
		}finally{
			
			class_mon.exit();
		}
	}
	
    /**
     * Backup the given file to filename.bak, removing the old .bak file if necessary.
     * If _make_copy is true, the original file will copied to backup, rather than moved.
     * @param _filename name of file to backup
     * @param _make_copy copy instead of move
     */
    public static void backupFile( final String _filename, final boolean _make_copy ) {
      backupFile( new File( _filename ), _make_copy );
    }
      
    /**
     * Backup the given file to filename.bak, removing the old .bak file if necessary.
     * If _make_copy is true, the original file will copied to backup, rather than moved.
     * @param _file file to backup
     * @param _make_copy copy instead of move
     */
    public static void backupFile( final File _file, final boolean _make_copy ) {
      if ( _file.length() > 0L ) {
        File bakfile = new File( _file.getAbsolutePath() + ".bak" );
        if ( bakfile.exists() ) bakfile.delete();
        if ( _make_copy ) {
          copyFile( _file, bakfile );
        }
        else {
          _file.renameTo( bakfile );
        }
      }
    }
    
    
    /**
     * Copy the given source file to the given destination file.
     * Returns file copy success or not.
     * @param _source_name source file name
     * @param _dest_name destination file name
     * @return true if file copy successful, false if copy failed
     */
    public static boolean copyFile( final String _source_name, final String _dest_name ) {
      return copyFile( new File(_source_name), new File(_dest_name));
    }
    
    /**
     * Copy the given source file to the given destination file.
     * Returns file copy success or not.
     * @param _source source file
     * @param _dest destination file
     * @return true if file copy successful, false if copy failed
     */
    /*
    // FileChannel.transferTo() seems to fail under certain linux configurations.
    public static boolean copyFile( final File _source, final File _dest ) {
      FileChannel source = null;
      FileChannel dest = null;
      try {
        if( _source.length() < 1L ) {
          throw new IOException( _source.getAbsolutePath() + " does not exist or is 0-sized" );
        }
        source = new FileInputStream( _source ).getChannel();
        dest = new FileOutputStream( _dest ).getChannel();
      
        source.transferTo(0, source.size(), dest);
        return true;
      }
      catch (Exception e) {
        Debug.out( e );
        return false;
      }
      finally {
        try {
          if (source != null) source.close();
          if (dest != null) dest.close();
        }
        catch (Exception ignore) {}
      }
    }
    */
    
    public static boolean copyFile( final File _source, final File _dest ) {
      try {
        copyFile( new FileInputStream( _source ), new FileOutputStream( _dest ) );
        return true;
      }
      catch( Throwable e ) {
      	Debug.printStackTrace( e );
        return false;
      }
    }
    
    public static boolean copyFile( final File _source, final OutputStream _dest, boolean closeInputStream ) {
        try {
          copyFile( new FileInputStream( _source ), _dest, closeInputStream );
          return true;
        }
        catch( Throwable e ) {
        	Debug.printStackTrace( e );
          return false;
        }
      }
    
    public static void 
    copyFile( 
    	final InputStream _source, 
    	final File _dest )
    
    	throws IOException
    {
    	FileOutputStream	dest = null;
    	
    	try{
    		dest = new FileOutputStream(_dest);
   
    		copyFile( _source, dest, true );
    		
    	}finally{
    		
    		if ( dest != null ){
    			
    			dest.close();
    		}
    	}
    }
    
    public static void 
    copyFile( 
      InputStream   is,
      OutputStream  os ) 
    throws IOException {
      copyFile(is,os,true);
    }
    
    public static void 
	copyFile( 
		InputStream		is,
		OutputStream	os,
		boolean 		closeInputStream )
	
		throws IOException
	{
    	try{
    		
    		if ( !(is instanceof BufferedInputStream )){
    			
    			is = new BufferedInputStream(is);
    		}
    		
    		byte[]	buffer = new byte[65536*2];
			
    		while(true){
    			
    			int	len = is.read(buffer);
    			
    			if ( len == -1 ){
    				
    				break;
    			}
    			
    			os.write( buffer, 0, len );
    		}
    	}finally{
    		try{
    			if(closeInputStream){
    			  is.close();
    			}
    		}catch( IOException e ){
    			
    		}
    		
    		os.close();
    	}
	}
    
    public static void
    copyFileOrDirectory(
    	File	from_file_or_dir,
    	File	to_parent_dir )
    
    	throws IOException
    {
    	if ( !from_file_or_dir.exists()){
    		
    		throw( new IOException( "File '" + from_file_or_dir.toString() + "' doesn't exist" ));
    	}
    	
    	if ( !to_parent_dir.exists()){
    		
    		throw( new IOException( "File '" + to_parent_dir.toString() + "' doesn't exist" ));
    	}
    	
    	if ( !to_parent_dir.isDirectory()){
    		
    		throw( new IOException( "File '" + to_parent_dir.toString() + "' is not a directory" ));
    	}
    	
    	if ( from_file_or_dir.isDirectory()){
    		
    		File[]	files = from_file_or_dir.listFiles();
    		
    		File	new_parent = new File( to_parent_dir, from_file_or_dir.getName());
    		

⌨️ 快捷键说明

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