目录
一、前言
二、实现思路
三、准备工作
四、本地测试模拟效果
1、未执行程序代码之前的效果图
2、执行程序代码之后的效果图
五、测试程序代码
程序经常会出现功能更新,bug修复的情况,这种情况下,怎么实现软件升级呢?本篇博客将介绍一种实现思路,大家可以借鉴借鉴,有错误的地方还望提出指正。后端是java实现的。
1、获取到旧版本和新版本的所有文件列表,根据新版本的文件名去旧版本中找,这种情况下会出现两种情况:
第一种:旧版本中找到了对应的文件,这时候计算一下两个文件的md5值,如果md5值一样,说明文件没有更新,不一样,则说明文件更新了。
第二种:旧版本中没有找到对应的文件,这个时候说明这个文件是新增的文件。
2、服务器上新建一个新版本目录、旧版本目录和更新文件目录,每次有更新,把所有文件上传到新版本目录中。点击“更新比对”按钮,后台执行比较程序,获取到所有新版本目录中的文件,和旧版本目录中的文件进行比较,把有更新的文件和新增的文件存储一份到更新文件目录中。最后把新版本目录中的文件全部覆盖掉旧版本目录中的文件,使新旧版本文件保持一致。客户端更新只需要下载更新文件目录中的文件覆盖掉客户端的文件即可。
1、在服务器上新建一个目录来存放我们软件的文件,如:新建一个“software”目录。在“software”目录下面新建三个目录,如:“new”、“old”、“update”。“new”目录用于存放新版本的文件。“old”用于存放旧版本的文件。“update”用于存放更新或者新增的文件。
2、每次软件有升级或者更新,把文件上传到“new”目录下面。
1、准备3个文件夹
2、新版本的文件目录如下
3、旧版本的目录如下
4、更新版本目录如下
程序执行结束之后,可以发现,有变更的文件已经移动到了“update”目录下面,并且“new”和“old”目录下面的文件也同步了。客户端下载更新只需要下载“update”目录下面的文件即可。下次有新的更新同理,只需要把程序的文件上传到“new”目录下面,执行一遍程序,即可完成文件的更新。
代码注释都写的很清楚,可以根据自己的需求优化,集成进自己的系统中。
package top.zywork.test;
import org.apache.commons.codec.digest.DigestUtils;
import java.io.*;
import java.util.ArrayList;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
/**
* 测试系统文件更新
* @author Red
*/
public class SysUpdateTest {
/**
* 获取一个文件夹下的所有文件全路径
* @param path 文件夹路径
* @param listFileName 存储文件名
*
*/
public static void getAllFileName(String path, ArrayList listFileName) {
File file = new File(path);
File[] files = file.listFiles();
String[] names = file.list();
if (names != null) {
String[] completNames = new String[names.length];
for (int i = 0; i < names.length; i++) {
completNames[i] = path + names[i];
}
listFileName.addAll(Arrays.asList(completNames));
}
for (File a : files) {
//如果文件夹下有子文件夹,获取子文件夹下的所有文件全路径。
if (a.isDirectory()) {
getAllFileName(a.getAbsolutePath() + "\\", listFileName);
}
}
}
/**
* 重命名文件
* @param filePath 重命名后文件的目标目录
* @param fileName 重命名前的完整文件路径
* @return
*/
public static void renameFile(String filePath, String fileName) {
SimpleDateFormat fmdate = new SimpleDateFormat("yyyyMMddHHmmssSSS");
String oldFileName = fileName;
File oldFile = new File(oldFileName);
String newFileName = filePath+File.separator+fmdate.format(new Date())+"."+fileName.split("\\.")[1];
File newFile = new File(newFileName);
if (oldFile.exists() && oldFile.isFile()) {
oldFile.renameTo(newFile);
}
}
/**
* 删除指定文件夹下面的文件及目录
* @param floder 需要删除文件夹目录
* @param deleteFloder 是否需要删除文件夹,true=需要、false=不需要
*/
public static void deleteFolder(File floder, boolean deleteFloder) {
File[] files = floder.listFiles();
if (null != files) {
for (File f :files) {
// 如果是文件夹,递归调用删除文件夹的方法
if (f.isDirectory()) {
deleteFolder(f, true);
} else {
f.delete();
}
}
}
if (deleteFloder) {
// 删除文件夹目录
floder.delete();
}
}
/**
* 删除指定的目录,该目录下的所有文件和目录也会删除
* @param srcDir 需要删除的目录
*/
public static void deleteFiles(String srcDir, boolean deleteFloder) {
File file = new File(srcDir);
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files != null && files.length > 0) {
for (File f : files) {
if (f.isDirectory()) {
deleteFiles(f.getAbsolutePath(), true);
} else {
f.delete();
}
}
}
}
if (deleteFloder) {
// 需要删除文件目录
file.delete();
}
}
/**
* 获取指定路径的文件的目录部分
* @param filePath 文件路径
* @return
*/
public static String getDirs(String filePath) {
return filePath.substring(0, filePath.lastIndexOf(File.separator));
}
/**
* 根据指定的路径,如果没有此路径则创建并返回绝对路径,否则直接返回绝对路径
* @param dirs 多级目录
* @return
*/
public static String mkdirs(String dirs) {
File path = new File(dirs);
if (!path.exists()) {
path.mkdirs();
}
return path.getAbsolutePath();
}
/**
* 根据完整的路径创建新文件
* @param filePath
*/
public static boolean createNewFile(String filePath) {
File file = new File(filePath);
if (!file.exists()) {
String dirs = getDirs(filePath);
mkdirs(dirs);
try {
return file.createNewFile();
} catch (IOException e) {
System.err.println("create new file error: " + e.getMessage());
return false;
}
}
return true;
}
/**
* 拷贝文件,支持任意文件类型
* @param srcPath
* @param destPath
*/
public static void copyFile(String srcPath, String destPath) {
File srcFile = new File(srcPath);
if (srcFile.exists()) {
if (createNewFile(destPath)) {
try (InputStream in = new FileInputStream(srcPath);
FileOutputStream out = new FileOutputStream(destPath)) {
byte[] bytes = new byte[1024];
int length;
while ((length = in.read(bytes)) != -1) {
out.write(bytes, 0, length);
}
} catch (IOException e) {
System.err.println("copyFile error: " + e.getMessage());
}
}
}
}
public static void handleFileUpdate(String basePath) throws Exception {
ArrayList newFileList = new ArrayList();
getAllFileName(basePath + "new" + File.separator, newFileList);
ArrayList oldFileList = new ArrayList();
getAllFileName(basePath + "old" + File.separator, oldFileList);
if (newFileList.isEmpty()) {
System.out.println("新版文件为空");
return;
}
if (oldFileList.isEmpty()) {
System.out.println("旧版文件为空");
return;
}
ArrayList updateFileList = new ArrayList<>();
System.out.println("开始更新文件:新版本文件总数:" + newFileList.size() + ",旧版本文件总数:" + oldFileList.size());
for (String newFilePath : newFileList) {
if (new File(newFilePath).isDirectory()) {
// 是文件夹,跳过循环
continue;
}
boolean updateFlag = false;
String newFileMd5 = DigestUtils.md5Hex(new FileInputStream(newFilePath));
for (String oldFilePath : oldFileList) {
if (new File(oldFilePath).isDirectory()) {
// 是文件夹,跳过循环
continue;
}
String oldFileMd5 = DigestUtils.md5Hex(new FileInputStream(oldFilePath));
// 暂时把新版文件名路径换成和旧版文件名路径一样的,用于判断文件是否存在旧版
String tempNewFilePath = newFilePath.replace(File.separator + "new" + File.separator, File.separator + "old" + File.separator);
if (oldFileList.contains(tempNewFilePath)) {
// 当前文件存在旧版本中
if (oldFilePath.equals(tempNewFilePath)) {
// 说明文件存在,判断这两个文件的md5值是否一样
if (!newFileMd5.equals(oldFileMd5)) {
// md5值不一样,说明文件有更新
updateFlag = true;
oldFileList.remove(oldFilePath);
break;
}
}
} else {
// 当前文件不存在旧版本中,是新增的文件
updateFlag = true;
break;
}
}
if (updateFlag) {
// 当前文件有更新或者是新增的文件
updateFileList.add(newFilePath);
}
}
if (updateFileList.isEmpty()) {
System.out.println("程序结束,没有需要更新的文件");
return;
}
System.out.println("开始处理更新文件:更新文件总数:" + updateFileList.size());
// 删除更新版本目录下面的所有文件
deleteFiles(basePath + "update" + File.separator, false);
for (String updateFilePath : updateFileList) {
String tempUpdateFilePath = updateFilePath.replace(File.separator + "new" + File.separator, File.separator + "update" + File.separator);
// 将需要更新的文件复制到更新版本中
copyFile(updateFilePath, tempUpdateFilePath);
}
System.out.println("更新文件处理完成,开始把新版本的文件复制到旧版本中");
// 同时把新版本的文件复制到旧版本中
deleteFiles(basePath + "old" + File.separator, false);
for (String newFilePath : newFileList) {
if (new File(newFilePath).isDirectory()) {
// 是文件夹,跳过循环
continue;
}
String tempOldFilePath = newFilePath.replace(File.separator + "new" + File.separator, File.separator + "old" + File.separator);
copyFile(newFilePath, tempOldFilePath);
}
System.out.println("程序处理结束");
}
public static void main(String[] args) throws Exception {
handleFileUpdate("C:\\Users\\Wangchenchen\\Desktop\\software\\");
}
}
所有代码都已经在上面了,如果你觉得对你有帮助,不妨给博主点个赞吧^_^
更多精彩好文请移步:http://wjhsmart.vip