System.Err 与 System.Out 流的重定向



package com.rainteen.framework.util.io;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;

/**
 * 重定向 System.err/System.out 流的类定义
 *
 * @author rainteen
 * @version 1.0
 */
@SuppressWarnings("all")
public class RedirectOutErr {
 private static Map instanceMap = new HashMap();
 /**
  * 同步锁
  */
 private static Boolean locked = new Boolean(false);

 private File logFile = null;
 private File logFileError = null;
 private File logFileOut = null;
 private ThreadLocal err = new ThreadLocal();
 private ThreadLocal out = new ThreadLocal();

 /**
  * 构造重定向类对象 将System.err/System.out重定向到同一个日志文件中
  * 注:因System.err/System.out是不同线程的I/O操作,不建议重定向到同一个日志中.
  *
  * @param logFile
  *            System.err/System.out重定向文件
  * @throws FileNotFoundException
  */
 // @SuppressWarnings("unchecked")
 private RedirectOutErr(final File logFile) {
  if (logFile == null) {
   throw new IllegalArgumentException("日志文件不能为空.");
  }
  this.logFile = logFile;
  try {
   if (!this.logFile.exists()) {
    this.logFile.createNewFile();
   } else {
    if (this.logFile.isDirectory()) {
     this.logFile.delete();
     this.logFile.createNewFile();
    }
   }
   this.out.set(new PrintStream(new BufferedOutputStream(
     new FileOutputStream(this.logFile))));
   this.err.set(new PrintStream(new BufferedOutputStream(
     new FileOutputStream(this.logFile))));
  } catch (FileNotFoundException fnfe) {
   fnfe.printStackTrace();
   throw new RuntimeException(fnfe.getMessage());
  } catch (IOException ioe) {
   ioe.printStackTrace();
   throw new RuntimeException(ioe.getMessage());
  }
 }

 /**
  * 将System.err重定向到 logFileError 文件, 将System.out重定向到 logFileOut 文件
  *
  * @param logFileError
  *            System.err重定向文件,错误日志
  * @param logFileOut
  *            System.out重定向文件,输出日志
  */
 // @SuppressWarnings("unchecked")
 private RedirectOutErr(final File logFileError, final File logFileOut) {
  if (logFileError == null && logFileOut == null) {
   throw new IllegalArgumentException("日志文件必须指定至少一个.");
  }

  try {
   if (logFileOut != null) {
    this.logFileOut = logFileOut;
    if (!this.logFileOut.exists())
     this.logFileOut.createNewFile();
    else if (this.logFileOut.exists()
      && this.logFileOut.isDirectory()) {
     this.logFileOut.delete();
     this.logFileOut.createNewFile();
    }
    this.out.set(new PrintStream(new BufferedOutputStream(
      new FileOutputStream(this.logFileOut))));
   }
   if (logFileError != null) {
    this.logFileError = logFileError;
    if (!this.logFileError.exists())
     this.logFileError.createNewFile();
    else if (this.logFileError.exists()
      && this.logFileError.isDirectory()) {
     this.logFileError.delete();
     this.logFileError.createNewFile();
    }
    this.err.set(new PrintStream(new BufferedOutputStream(
      new FileOutputStream(this.logFileError))));
   }

  } catch (FileNotFoundException fnfe) {
   fnfe.printStackTrace();
   throw new RuntimeException(fnfe.getMessage());
  } catch (IOException ioe) {
   ioe.printStackTrace();
   throw new RuntimeException(ioe.getMessage());
  }
 }

 /**
  * 多例模式工厂方法 获取一个实例 将 System.err/System.out 都定向到该 logFile 文件
  * 注:因System.err/System.out是不同线程的I/O操作,不建议重定向到同一个日志中.
  *
  * @param logFile
  *            System.err/System.out的重定向文件
  * @return
  */
 public synchronized static RedirectOutErr getInstance(final File logFile) {
  if (logFile == null)
   throw new IllegalArgumentException("参数logFile不能为空.");
  String logPath = logFile.toString();
  RedirectOutErr redirectOutErr = (RedirectOutErr) RedirectOutErr.instanceMap
    .get("Both:" + logPath);
  if (redirectOutErr == null) {
   redirectOutErr = new RedirectOutErr(logFile);
   RedirectOutErr.instanceMap.put("Both:" + logPath, redirectOutErr);
  }
  return redirectOutErr;
 }

 /**
  * 多例模式工厂方法 以 System.err 重定向文件logFileError, System.out 的重定向文件 logFileOut实例化
  *
  * @param logFileError
  *            System.err 的重定向文件
  * @param logFileOut
  *            System.out 的重定向文件
  * @return
  */
 public synchronized static RedirectOutErr getInstance(
   final File logFileError, final File logFileOut) {
  if (logFileError == null && logFileOut == null)
   throw new IllegalArgumentException(
     "参数 logFileError|logFileOut 不能全为空.");
  String logError = "";
  String logOut = "";
  if (logFileError != null)
   logError = logFileError.toString();
  if (logFileOut != null)
   logOut = logFileOut.toString();
  RedirectOutErr redirectOutErr = (RedirectOutErr) RedirectOutErr.instanceMap
    .get("Err:" + logError + "|Out:" + logOut);
  if (redirectOutErr == null) {
   redirectOutErr = new RedirectOutErr(logFileError, logFileOut);
   RedirectOutErr.instanceMap.put(
     "Err:" + logError + "|Out:" + logOut, redirectOutErr);
  }
  return redirectOutErr;
 }

 public boolean isLocked() {
  return locked.booleanValue();
 }

 /**
  * 此处的 synchronized 非常重要,否则会导致死锁
  */
 public synchronized void lock() {
  this.locked = new Boolean(true);
  // locked.set(true);
 }

 /**
  * 此处的 synchronized 非常重要,否则会导致死锁
  */
 public synchronized void unlock() {
  this.locked = new Boolean(false);
 }

 /**
  * 析构
  */
 protected void finalize() throws Throwable {
  if (this.out.get() != null)
   ((PrintStream) this.out.get()).close();
  if (this.err.get() != null)
   ((PrintStream) this.err.get()).close();
  this.out = null;
  this.err = null;
  RedirectOutErr.instanceMap.clear();
  RedirectOutErr.instanceMap = null;
  this.logFile = null;
  this.logFileOut = null;
  this.logFileError = null;
  super.finalize();
 }

 /**
  * 用于销毁所有实例
  */
 public void destory() {
  if (this.out.get() != null)
   ((PrintStream) this.out.get()).close();
  if (this.err.get() != null)
   ((PrintStream) this.err.get()).close();
  this.out = null;
  this.err = null;
  RedirectOutErr.instanceMap.clear();
  RedirectOutErr.instanceMap = null;
  this.logFile = null;
  this.logFileOut = null;
  this.logFileError = null;
  System.gc();
 }

 /**
  * 开启重定向, 只有已经为实例指定了对应文件的情况下才有效.
  */
 public RedirectOutErr onRedirect() {
  synchronized (this.locked) {
   while (true) {
    try {
     if (!this.isLocked()) {
      this.lock();
      if (this.err.get() != null)
       System.setErr(((PrintStream) this.err.get()));
      this.unlock();
      this.locked.notify();
      break;
     } else {
      this.locked.wait();
     }
    } catch (InterruptedException ie) {
     ie.printStackTrace();
    }
   }
   while (true) {
    try {
     if (!this.isLocked()) {
      this.lock();
      if (this.out.get() != null) {
       System.setOut(((PrintStream) this.out.get()));
      }
      this.unlock();
      this.locked.notify();
      break;
     } else {
      this.locked.wait();
     }
    } catch (InterruptedException ie) {
     ie.printStackTrace();
    }
   }
  }
  return this;
 }

 /**
  * 关闭重定向, 恢复System.err/System.out的原有行为特性
  */
 public RedirectOutErr offRedirect() {
  synchronized (this.locked) {
   while (true) {
    try {
     if (!this.isLocked()) {
      FileOutputStream fdErr = new FileOutputStream(
        FileDescriptor.err);
      this.lock();
      // synchronized (this.locked) {
      System.setErr(new PrintStream(new BufferedOutputStream(
        fdErr, 128), true));
      // }
      this.unlock();
      this.locked.notify();
      break;
     } else {
      this.locked.wait();
     }
    } catch (InterruptedException ie) {
     ie.printStackTrace();
    }
   }
   while (true) {
    try {
     if (!this.isLocked()) {
      FileOutputStream fdOut = new FileOutputStream(
        FileDescriptor.out);
      this.lock();
      // synchronized (this.locked) {
      System.setOut(new PrintStream(new BufferedOutputStream(
        fdOut, 128), true));
      // }
      this.unlock();
      this.locked.notify();
      break;
     } else {
      this.locked.wait();
     }
    } catch (InterruptedException ie) {
     ie.printStackTrace();
    }
   }
  }

  return this;
 }

 /**
  * 开启System.out的重定向
  */
 public RedirectOutErr onRedirectOut() {
  if (this.out.get() == null)
   throw new IllegalStateException("没有为System.out指定重定向文件");
  synchronized (this.locked) {
   while (true) {
    try {
     if (!this.isLocked()) {
      this.lock();
      System.setOut(((PrintStream) this.out.get()));
      this.unlock();
      this.locked.notify();
      break;
     } else {
      this.locked.wait();
     }
    } catch (InterruptedException ie) {
     ie.printStackTrace();
    }
   }
  }

  return this;
 }

 /**
  * 关闭System.out的重定向
  */
 public RedirectOutErr offRedirectOut() {
  FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
  synchronized (this.locked) {
   while (true) {
    try {
     if (!this.isLocked()) {
      this.lock();
      System.setOut(new PrintStream(new BufferedOutputStream(
        fdOut, 128), true));
      this.unlock();
      this.locked.notify();
      break;
     } else {
      this.locked.wait();
     }
    } catch (InterruptedException ie) {
     ie.printStackTrace();
    }
   }
  }

  return this;
 }

 /**
  * 开启System.err的重定向
  */
 public RedirectOutErr onRedirectError() {
  if (this.err.get() == null)
   throw new IllegalStateException("没有为System.err指定重定向文件");
  synchronized (this.locked) {
   while (true) {
    try {
     if (!this.isLocked()) {
      this.lock();
      System.setErr(((PrintStream) this.err.get()));
      this.unlock();
      this.locked.notify();
      break;
     } else {
      this.locked.wait();
     }
    } catch (InterruptedException ie) {
     ie.printStackTrace();
    }
   }
  }

  return this;
 }

 /**
  * 关闭System.err的重定向
  */
 public RedirectOutErr offRedirectError() {
  FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
  synchronized (this.locked) {
   while (true) {
    try {
     if (!this.isLocked()) {
      this.lock();
      System.setErr(new PrintStream(new BufferedOutputStream(
        fdErr, 128), true));
      this.unlock();
      this.locked.notify();
      break;
     } else {
      this.locked.wait();
     }
    } catch (InterruptedException ie) {
     ie.printStackTrace();
    }
   }
  }

  return this;
 }

 public static void main(String[] args) {
  
 }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值