欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java使用nio2拷贝文件的示例

程序员文章站 2024-02-26 19:14:58
这个程序只是为了更方便的进行拷贝文件(夹)而创造。1.可以不用新建文件夹,就像windows的复制粘贴一样简单。2.有简单的出错重连机制3.不需要重复拷贝,差异化复制文件。...

这个程序只是为了更方便的进行拷贝文件(夹)而创造。
1.可以不用新建文件夹,就像windows的复制粘贴一样简单。
2.有简单的出错重连机制
3.不需要重复拷贝,差异化复制文件。
4.拷贝文件夹的时候可以不用复制全路径,只关注需要拷贝的文件夹。
5.程序做了简单的必要检查,效率也不算低。
6.使用的是7的nio2的新api。

复制代码 代码如下:

import java.io.ioexception;
import java.nio.file.filevisitresult;
import java.nio.file.filevisitor;
import java.nio.file.files;
import java.nio.file.path;
import java.nio.file.paths;
import java.nio.file.standardcopyoption;
import java.nio.file.attribute.basicfileattributes;
import java.nio.file.attribute.filetime;
import java.util.stack;

import org.apache.log4j.logger;

import com.xyq.myfile.cope.entity.pathtype;
import com.xyq.util.md5util;

/***
 * 基于jdk7的拷贝算法
 *
 * @author xyq
 *
 */
public class myfiles2 {

 private string src;
 private string tar;
 private path srcpath;
 private path tarpath;
 private int recount = 3;
 private boolean iscover = false;
 private boolean usemd5 = false;
 private int subnamenum = 0;
 // log4j对象
 private logger logger;
 // 在文件夹-->文件夹模式中,是否拷贝全路径,默认不拷贝
 private boolean iscopeallpath = false;

 public myfiles2(string src, string tar) {

  this.src = src;
  this.tar = tar;
  this.srcpath = paths.get(src);
  this.tarpath = paths.get(tar);
 }

 public myfiles2() {
 }

 public string getsrc() {
  return src;
 }

 public void setsrc(string src) {
  this.src = src;
  this.srcpath = paths.get(src);
 }

 public string gettar() {
  return tar;
 }

 public void settar(string tar) {
  this.tar = tar;
  this.tarpath = paths.get(tar);
 }

 public int getrecount() {
  return recount;
 }

 public void setrecount(int recount) {
  this.recount = recount;
 }

 public boolean iscover() {
  return iscover;
 }

 public void setcover(boolean iscover) {
  this.iscover = iscover;
 }

 public logger getlogger() {
  return logger;
 }

 public void setlogger(logger logger) {
  this.logger = logger;
 }

 public boolean isusemd5() {
  return usemd5;
 }

 public void setusemd5(boolean usemd5) {
  this.usemd5 = usemd5;
 }

 public boolean iscopeallpath() {
  return iscopeallpath;
 }

 public void setcopeallpath(boolean iscopeallpath) {
  this.iscopeallpath = iscopeallpath;
 }

 public boolean copefilecore(pathtype... types) {

  if (initcheck() && initcheck2s(this.srcpath, false))
   return copefilecore(this.srcpath, this.tarpath, recount, iscover,
     types);
  return false;
 }

 private boolean initcheck() {

  if (this.srcpath == null) {
   loginfo("原始路径未设置,程序无法启动~~");
   return false;
  } else if (this.tarpath == null) {
   loginfo("目标路径未设置,程序无法启动~~");
   return false;
  } else if (!files.exists(srcpath)) {
   loginfo("原始路径不存在,程序无法启动~~");
   return false;
  } else if (!files.exists(tarpath.getroot())) {
   loginfo("目标路径的根盘符不存在,程序无法启动~~");
   return false;
  }
  return true;
 }

 private boolean initcheck2s(path path, boolean dorf) {

  if (!files.isdirectory(path)) {
   if (dorf) {
    loginfo(path + "不是一个有效的文件夹");
    return false;
   }
  } else if (!dorf) {
   loginfo(path + "不是一个有效的文件");
   return false;
  }
  return true;
 }

 /****
  * 拷贝文件算法
  *
  * @param path1
  *            原始路径
  * @param path2
  *            目标路径
  * @param recount
  *            重复次数
  * @param iscover
  *            是否覆盖拷贝
  * @param types
  *            你所写的目标路径是文件还是文件夹,可以不写,默认是文件
  * @return
  */
 public boolean copefilecore(path path1, path path2, int recount,
   boolean iscover, pathtype... types) {

  // 如果原始文件不存在,就直接异常
  if (!initcheck() || !initcheck2s(path1, false))
   return false;
  pathtype type = pathtype.files;
  if (types != null && types.length > 0) {
   type = types[0];
   // 如果目标是一个文件夹,并且指定是往一个文件夹拷贝的时候
   if (type.equals(pathtype.dirs)) {
    path2 = paths.get(path2.tostring(), path1.getfilename()
      .tostring());
   }
  }
  // 如果目标文件已经存在,就判断是否相同,相同就不用拷贝了
  if (files.exists(path2)) {
   if (files.isdirectory(path2) && pathtype.files.equals(type)) {
    loginfo(path2 + "已经存在,它是一个文件夹而不是文件");
    return false;
   }
   if (issamefile(path1, path2, usemd5))
    return true;
  }
  // 当目标文件不存在的时候
  else {
   path parpath = path2.getparent();
   // 如果目标文件的父类文件夹不存在,就尝试创建
   if (!files.exists(parpath))
    for (int i = 1; i < recount; i++) {
     try {
      files.createdirectories(parpath);
      break;
     } catch (exception e) {
      if (i == recount) {
       loginfo(e);
       return false;
      }
     }
    }
  }

  for (int i = 1; i <= recount; i++) {
   try {
    if (iscover)
     files.copy(path1, path2,
       standardcopyoption.replace_existing,
       standardcopyoption.copy_attributes);
    else
     files.copy(path1, path2, standardcopyoption.copy_attributes);
    // 同步最后修改时间
    synlastfiletime(path1, path2);
    break;
   } catch (ioexception e) {
    // 如果在指定时间内都无法完成拷贝,那么就果断记录到异常信息中
    if (i == recount) {
     loginfo(e);
     return false;
    }
   }
  }
  return true;

 }

 public void copedir() {

  if (!initcheck() || !initcheck2s(srcpath, true))
   return;
  copedir(this.srcpath.tostring(), this.tarpath.tostring());
 }

 /***
  * 拷贝文件夹保护层
  *
  * @param path1
  * @param path2
  */
 public void copedir(string path1, final string path2) {

  if (!initcheck() || !initcheck2s(srcpath, true))
   return;
  path p1 = paths.get(path1);
  final path tarpath = paths.get(path2);
  if (!iscopeallpath)
   subnamenum = srcpath.getnamecount() - 1;
  try {
   files.walkfiletree(p1, new filevisitor<path>() {

    path p2 = null;
    stack<path> dirstack = new stack<path>();

    @override
    public filevisitresult previsitdirectory(path dir,
      basicfileattributes attrs) throws ioexception {

     // 当使用不拷贝全路径时,作为本文件夹的名字节点的记录位置
     // if (!copeallpath)
     /****
      * 如果是相同的文件夹,那么就跳过无需拷贝.
      */
     if (issamepath(dir, tarpath)) {
      system.out.println("是相同的,跳过!!!!!!!!!!!!!!!!!");
      return filevisitresult.skip_subtree;
     }
     p2 = replacepath(dir, path2, subnamenum);
     if (dir.tofile().length() == 0 && !files.exists(p2))
      files.createdirectories(p2);
     dirstack.push(p2);
     return filevisitresult.continue;

    }

    @override
    public filevisitresult visitfile(path file,
      basicfileattributes attrs) throws ioexception {

     path tofilepath = paths.get(dirstack.peek().tostring(),
       file.getfilename().tostring());
     copefilecore(file, tofilepath, 3, true);
     return filevisitresult.continue;

    }

    @override
    public filevisitresult visitfilefailed(path file,
      ioexception exc) throws ioexception {

     return filevisitresult.continue;
    }

    @override
    public filevisitresult postvisitdirectory(path dir,
      ioexception exc) throws ioexception {
     if (!dirstack.isempty())
      dirstack.pop();
     return filevisitresult.continue;
    }

   });
  } catch (ioexception e) {
   loginfo(e);
  }
 }

 /***
  * 替换path
  *
  * @param path1
  * @param path2
  * @return
  */
 private path replacepath(path path1, string path2, int namecountnum) {

  if (path1.getnamecount() == 0 && path1.equals(path1.getroot()))
   return paths.get(path2);
  return paths.get(path2,
    path1.subpath(namecountnum, path1.getnamecount()).tostring());
 }

 /***
  * 要么是地址完全相同,要么就是原始文件的父类与目标相同,因为程序支持拷贝到父类
  *
  * @param path1
  * @param path2
  * @return
  */
 private boolean issamepath(path path1, path path2) {

  if (path1.equals(path2))
   return true;
  return false;
 }

 /***
  * 同步文件的修改时间
  *
  * @param path1
  * @param path2
  * @return
  */
 public boolean synlastfiletime(path path1, path path2) {

  filetime srcpathtime;
  try {
   srcpathtime = files.getlastmodifiedtime(path1);
   files.setlastmodifiedtime(path2, srcpathtime);
   return srcpathtime.equals(files.getlastmodifiedtime(path2));
  } catch (ioexception e) {
   loginfo(e);
   return false;
  }
 }

 /***
  * 判断两个文件是否相同
  *
  * @param path1
  * @param path2
  * @return
  */
 public boolean issamefile(path path1, path path2, boolean usemd5) {

  try {
   // 只要两个文件长度不一致,就绝对不是一个文件
   if (files.size(path1) != files.size(path2))
    return false;
   // 如果是最后的修改时间不一样,就直接使用md5验证
   else if (!files.getlastmodifiedtime(path1).equals(
     files.getlastmodifiedtime(path2))
     || usemd5)
    return md5util.getfilemd5string(path1.tofile()).equals(
      md5util.getfilemd5string(path2.tofile()));
   return true;
  } catch (exception e) {
   loginfo(e);
   return false;
  }
 }

 /***
  * 针对异常处理的
  */
 private void loginfo(exception e) {

  if (this.logger != null)
   logger.error(e.getmessage());
  else if (e != null)
   system.out.println("异常:" + e.getmessage());
 }

 private void loginfo(string errormessage) {

  if (this.logger != null)
   logger.error(errormessage);
  else
   system.out.println("异常:" + errormessage);
 }

 public static void main(string[] args) {

  // new myfiles2("e:/t/1.txt", "e:/3/33").copefilecore();
  myfiles2 my = new myfiles2("e:/ttt/tt/t/1.txt", "e:/3/33.txt");
  my.copefilecore(pathtype.dirs);
 }
}

复制代码 代码如下:

public enum pathtype {

 files,dirs;
}

复制代码 代码如下:

import java.io.closeable;

public class closeioutil {

 /***
  * 关闭io流
  *
  * @param cls
  */
 public static void closeall(closeable... cls) {

  if (cls != null) {
   for (closeable cl : cls) {
    try {
     if (cl != null)
      cl.close();
    } catch (exception e) {

    } finally {
     cl = null;
    }
   }
  }
 }
}

复制代码 代码如下:

import java.io.bufferedinputstream;
import java.io.file;
import java.io.fileinputstream;
import java.io.ioexception;
import java.io.inputstream;
import java.security.messagedigest;
import java.security.nosuchalgorithmexception;

public class md5util {

 protected static char hexdigits[] = { '0', '1', '2', '3', '4', '5', '6',
   '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
 protected static messagedigest messagedigest = null;
 static {
  try {
   messagedigest = messagedigest.getinstance("md5");
  } catch (nosuchalgorithmexception e) {
   e.printstacktrace();
  }
 }

 public static string getfilemd5string(file file) throws ioexception {

  /***
   * mappedbytebuffer是nio的api,使用这个api会有一个bug,
   * 当使用 filechannel.map 方法时,mappedbytebuffer 已经在系统内占用了一个句柄,
   * 而使用 filechannel.close 方法是无法释放这个句柄的,、
   * 且filechannel有没有提供类似 unmap 的方法,因此会出现无法删除文件的情况。
   */
  // fileinputstream in = new fileinputstream(file);
  // filechannel ch = in.getchannel();
  // mappedbytebuffer bytebuffer = ch.map(filechannel.mapmode.read_only,
  // 0,
  // file.length());

  inputstream fis = null;
  bufferedinputstream bis = null;
        fis = new fileinputstream(file); 
        bis = new bufferedinputstream(fis);
        byte[] buffer = new byte[2048]; 
        int numread = 0; 
        while ((numread = bis.read(buffer)) > 0) { 
            messagedigest.update(buffer, 0, numread); 
        } 
        closeioutil.closeall(bis,fis);
        return buffertohex(messagedigest.digest()); 
 }

 public static string getmd5string(string s) {
  return getmd5string(s.getbytes());
 }

 public static string getmd5string(byte[] bytes) {
  messagedigest.update(bytes);
  return buffertohex(messagedigest.digest());
 }

 private static string buffertohex(byte bytes[]) {
  return buffertohex(bytes, 0, bytes.length);
 }

 private static string buffertohex(byte bytes[], int m, int n) {
  stringbuffer stringbuffer = new stringbuffer(2 * n);
  int k = m + n;
  for (int l = m; l < k; l++) {
   appendhexpair(bytes[l], stringbuffer);
  }
  return stringbuffer.tostring();
 }

 private static void appendhexpair(byte bt, stringbuffer stringbuffer) {
  char c0 = hexdigits[(bt & 0xf0) >> 4];
  char c1 = hexdigits[bt & 0xf];
  stringbuffer.append(c0);
  stringbuffer.append(c1);
 }

 public static boolean checkpassword(string password, string md5pwdstr) {
  string s = getmd5string(password);
  return s.equals(md5pwdstr);
 }

 public static void main(string[] args) throws ioexception {

  file big = new file("e:/sss.txt");
  string md5 = getfilemd5string(big);
  //
  // long end = system.currenttimemillis();
  // system.out.println("md5:" + md5);
  // system.out.println("time:" + ((end - begin) / 1000) + "s");

  system.out.println(md5);

 }

}

复制代码 代码如下:

import java.io.bufferedinputstream;
import java.io.file;
import java.io.fileinputstream;
import java.io.ioexception;
import java.io.inputstream;
import java.security.messagedigest;
import java.security.nosuchalgorithmexception;

public class md5util {

 protected static char hexdigits[] = { '0', '1', '2', '3', '4', '5', '6',
   '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
 protected static messagedigest messagedigest = null;
 static {
  try {
   messagedigest = messagedigest.getinstance("md5");
  } catch (nosuchalgorithmexception e) {
   e.printstacktrace();
  }
 }

 public static string getfilemd5string(file file) throws ioexception {

  /***
   * mappedbytebuffer是nio的api,使用这个api会有一个bug,
   * 当使用 filechannel.map 方法时,mappedbytebuffer 已经在系统内占用了一个句柄,
   * 而使用 filechannel.close 方法是无法释放这个句柄的,、
   * 且filechannel有没有提供类似 unmap 的方法,因此会出现无法删除文件的情况。
   */
  // fileinputstream in = new fileinputstream(file);
  // filechannel ch = in.getchannel();
  // mappedbytebuffer bytebuffer = ch.map(filechannel.mapmode.read_only,
  // 0,
  // file.length());

  inputstream fis = null;
  bufferedinputstream bis = null;
        fis = new fileinputstream(file); 
        bis = new bufferedinputstream(fis);
        byte[] buffer = new byte[2048]; 
        int numread = 0; 
        while ((numread = bis.read(buffer)) > 0) { 
            messagedigest.update(buffer, 0, numread); 
        } 
        closeioutil.closeall(bis,fis);
        return buffertohex(messagedigest.digest()); 
 }

 public static string getmd5string(string s) {
  return getmd5string(s.getbytes());
 }

 public static string getmd5string(byte[] bytes) {
  messagedigest.update(bytes);
  return buffertohex(messagedigest.digest());
 }

 private static string buffertohex(byte bytes[]) {
  return buffertohex(bytes, 0, bytes.length);
 }

 private static string buffertohex(byte bytes[], int m, int n) {
  stringbuffer stringbuffer = new stringbuffer(2 * n);
  int k = m + n;
  for (int l = m; l < k; l++) {
   appendhexpair(bytes[l], stringbuffer);
  }
  return stringbuffer.tostring();
 }

 private static void appendhexpair(byte bt, stringbuffer stringbuffer) {
  char c0 = hexdigits[(bt & 0xf0) >> 4];
  char c1 = hexdigits[bt & 0xf];
  stringbuffer.append(c0);
  stringbuffer.append(c1);
 }

 public static boolean checkpassword(string password, string md5pwdstr) {
  string s = getmd5string(password);
  return s.equals(md5pwdstr);
 }

 public static void main(string[] args) throws ioexception {

  file big = new file("e:/sss.txt");
  string md5 = getfilemd5string(big);
  //
  // long end = system.currenttimemillis();
  // system.out.println("md5:" + md5);
  // system.out.println("time:" + ((end - begin) / 1000) + "s");

  system.out.println(md5);

 }
}