java使用nio2拷貝文件的示例
這個(gè)程序只是為了更方便的進(jìn)行拷貝文件(夾)而創(chuàng)造。
1.可以不用新建文件夾,就像windows的復(fù)制粘貼一樣簡(jiǎn)單。
2.有簡(jiǎn)單的出錯(cuò)重連機(jī)制
3.不需要重復(fù)拷貝,差異化復(fù)制文件。
4.拷貝文件夾的時(shí)候可以不用復(fù)制全路徑,只關(guān)注需要拷貝的文件夾。
5.程序做了簡(jiǎn)單的必要檢查,效率也不算低。
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對(duì)象
private Logger logger;
// 在文件夾-->文件夾模式中,是否拷貝全路徑,默認(rèn)不拷貝
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("原始路徑未設(shè)置,程序無(wú)法啟動(dòng)~~");
return false;
} else if (this.tarPath == null) {
logInfo("目標(biāo)路徑未設(shè)置,程序無(wú)法啟動(dòng)~~");
return false;
} else if (!Files.exists(srcPath)) {
logInfo("原始路徑不存在,程序無(wú)法啟動(dòng)~~");
return false;
} else if (!Files.exists(tarPath.getRoot())) {
logInfo("目標(biāo)路徑的根盤符不存在,程序無(wú)法啟動(dòng)~~");
return false;
}
return true;
}
private boolean initCheck2s(Path path, boolean dOrF) {
if (!Files.isDirectory(path)) {
if (dOrF) {
logInfo(path + "不是一個(gè)有效的文件夾");
return false;
}
} else if (!dOrF) {
logInfo(path + "不是一個(gè)有效的文件");
return false;
}
return true;
}
/****
* 拷貝文件算法
*
* @param path1
* 原始路徑
* @param path2
* 目標(biāo)路徑
* @param reCount
* 重復(fù)次數(shù)
* @param isCover
* 是否覆蓋拷貝
* @param types
* 你所寫的目標(biāo)路徑是文件還是文件夾,可以不寫,默認(rèn)是文件
* @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];
// 如果目標(biāo)是一個(gè)文件夾,并且指定是往一個(gè)文件夾拷貝的時(shí)候
if (type.equals(PathType.DIRS)) {
path2 = Paths.get(path2.toString(), path1.getFileName()
.toString());
}
}
// 如果目標(biāo)文件已經(jīng)存在,就判斷是否相同,相同就不用拷貝了
if (Files.exists(path2)) {
if (Files.isDirectory(path2) && PathType.FILES.equals(type)) {
logInfo(path2 + "已經(jīng)存在,它是一個(gè)文件夾而不是文件");
return false;
}
if (isSameFile(path1, path2, useMd5))
return true;
}
// 當(dāng)目標(biāo)文件不存在的時(shí)候
else {
Path parPath = path2.getParent();
// 如果目標(biāo)文件的父類文件夾不存在,就嘗試創(chuàng)建
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);
// 同步最后修改時(shí)間
synLastFileTime(path1, path2);
break;
} catch (IOException e) {
// 如果在指定時(shí)間內(nèi)都無(wú)法完成拷貝,那么就果斷記錄到異常信息中
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());
}
/***
* 拷貝文件夾保護(hù)層
*
* @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 {
// 當(dāng)使用不拷貝全路徑時(shí),作為本文件夾的名字節(jié)點(diǎn)的記錄位置
// if (!copeAllPath)
/****
* 如果是相同的文件夾,那么就跳過(guò)無(wú)需拷貝.
*/
if (isSamePath(dir, tarPath)) {
System.out.println("是相同的,跳過(guò)!!!!!!!!!!!!!!!!!");
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());
}
/***
* 要么是地址完全相同,要么就是原始文件的父類與目標(biāo)相同,因?yàn)槌绦蛑С挚截惖礁割?BR> *
* @param path1
* @param path2
* @return
*/
private boolean isSamePath(Path path1, Path path2) {
if (path1.equals(path2))
return true;
return false;
}
/***
* 同步文件的修改時(shí)間
*
* @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;
}
}
/***
* 判斷兩個(gè)文件是否相同
*
* @param path1
* @param path2
* @return
*/
public boolean isSameFile(Path path1, Path path2, boolean useMd5) {
try {
// 只要兩個(gè)文件長(zhǎng)度不一致,就絕對(duì)不是一個(gè)文件
if (Files.size(path1) != Files.size(path2))
return false;
// 如果是最后的修改時(shí)間不一樣,就直接使用MD5驗(yàn)證
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;
}
}
/***
* 針對(duì)異常處理的
*/
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 {
/***
* 關(guān)閉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,使用這個(gè)API會(huì)有一個(gè)bug,
* 當(dāng)使用 FileChannel.map 方法時(shí),MappedByteBuffer 已經(jīng)在系統(tǒng)內(nèi)占用了一個(gè)句柄,
* 而使用 FileChannel.close 方法是無(wú)法釋放這個(gè)句柄的,、
* 且FileChannel有沒(méi)有提供類似 unmap 的方法,因此會(huì)出現(xiàn)無(wú)法刪除文件的情況。
*/
// 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,使用這個(gè)API會(huì)有一個(gè)bug,
* 當(dāng)使用 FileChannel.map 方法時(shí),MappedByteBuffer 已經(jīng)在系統(tǒng)內(nèi)占用了一個(gè)句柄,
* 而使用 FileChannel.close 方法是無(wú)法釋放這個(gè)句柄的,、
* 且FileChannel有沒(méi)有提供類似 unmap 的方法,因此會(huì)出現(xiàn)無(wú)法刪除文件的情況。
*/
// 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);
}
}
相關(guān)文章
Java利用Socket和IO流實(shí)現(xiàn)文件的上傳與下載
本文主要介紹了Java利用Socket和IO流實(shí)現(xiàn)文件的上傳與下載,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04淺析Java 常用的 4 種加密方式(MD5+Base64+SHA+BCrypt)
這篇文章主要介紹了Java 常用的 4 種加密方式(MD5+Base64+SHA+BCrypt),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-10-10ScheduledThreadPoolExecutor巨坑解決
這篇文章主要為大家介紹了使用ScheduledThreadPoolExecutor遇到的巨坑解決示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02Java設(shè)計(jì)模式之創(chuàng)建者模式簡(jiǎn)介
這篇文章主要介紹了Java設(shè)計(jì)模式之創(chuàng)建者模式,需要的朋友可以參考下2014-07-07Spring Boot(二)之web綜合開(kāi)發(fā)
本篇文章為大家介紹spring boot的其它特性(有些未必是spring boot體系桟的功能,但是是spring特別推薦的一些開(kāi)源技術(shù)本文也會(huì)介紹),對(duì)了這里只是一個(gè)大概的介紹,特別詳細(xì)的使用我們會(huì)在其它的文章中來(lái)展開(kāi)說(shuō)明2017-05-05Java安全之Filter權(quán)限繞過(guò)的實(shí)現(xiàn)
在一些需要挖掘一些無(wú)條件RCE中,大部分類似于一些系統(tǒng)大部分地方都做了權(quán)限控制的,而這時(shí)候想要利用權(quán)限繞過(guò)就顯得格外重要,本文就介紹了如何實(shí)現(xiàn),一起來(lái)了解一下2021-05-05IDEA利用jclasslib 修改class文件的實(shí)現(xiàn)
這篇文章主要介紹了IDEA利用jclasslib 修改class文件的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02Java實(shí)現(xiàn)發(fā)送郵件并攜帶附件
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)發(fā)送郵件并攜帶附件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09