java使用nio2拷贝文件的示例
这个程序只是为了更方便的进行拷贝文件(夹)而创造。
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);
}
}
上一篇: PHP基于单例模式编写PDO类的方法
下一篇: JavaWeb表单注册界面的实现方法