做外贸 访问国外网站,申请手机网站,义乌网站建设公司,房地产企业网站开发Java项目中调用bat批处理配合使用BCP进行多用户数据的备份一、项目需求最近项目中需要对数据库(Sql Server系列数据库)进行备份。项目中的需求不是简单的整个数据库的备份#xff0c;而是根据用户来备份#xff0c;具体的备份策略如下#xff1a;①系统为某一赛事管理类型的…Java项目中调用bat批处理配合使用BCP进行多用户数据的备份一、项目需求最近项目中需要对数据库(Sql Server系列数据库)进行备份。项目中的需求不是简单的整个数据库的备份而是根据用户来备份具体的备份策略如下①系统为某一赛事管理类型的系统整个系统分为几部分前半部分的处理是在服务器上处理后半部分的处理是在用户自己的客户端中处理。不同的赛事对应不同的用户用户将需要的数据提交给系统进行处理。②系统在处理完数据之后用户可以导出自己赛事相关的数据了这个导出实际上做的就是个备份数据库只不过只备份属于自己的数据库。然后下载系统的处理结果很显然各个用户的数据是不相同的。③用户下载自己备份的数据库文件(这些个文件会打包成zip压缩包)再导入自己的客户端系统中。整个系统使用的关键是程序中调用bcp命令的时候传递用户相关的参数过去就OK了。处理流程如图1-1所示图1-1 处理流程二、解决方案本文提出的是使用Runtime.getRuntime().exec()调用批处理文件程序中传递相关参数给bcp命令。关于BCP命令的详解微软的MSDN上面写的非常的详细在此就不赘述了下面的一段话引用自微软的msdn上面的一段介绍bcp 实用工具可以在 Microsoft SQL Server 实例和用户指定格式的数据文件间大容量复制数据。使用 bcp 实用工具可以将大量新行导入 SQL Server 表或将表数据导出到数据文件。除非与 queryout 选项一起使用否则使用该实用工具不需要了解 Transact-SQL 知识。若要将数据导入表中必须使用为该表创建的格式文件或者必须了解表的结构以及对于该表中的列有效的数据类型。三、系统的实现实现主要分为批处理文件的编写和Java程序中的调用两部分这两部分完成之后第一部分中的后续问题就好解决了。①批处理编写编写的批处理文件如下也就是使用bcp工具来进行备份这里只列出部分表代码都是一样的使用的时候稍微修改下即可Title 根据userId导出的表bcp SELECT * FROM sportSys.dbo.competitions wheresportSys.dbo.competitions.userId%1 queryout %2competitions.xls -T -c%3log.txtecho competitions表备份已完成%3log.txtbcp SELECT * FROM sportSys.dbo.item wheresportSys.dbo.item.userId%1 queryout %2item.xls -T -c%3log.txtecho item表备份已完成%3log.txtbcp SELECT * FROM sportSys.dbo.itemType wheresportSys.dbo.itemType.userId%1 queryout %2itemType.xls -T -c%3log.txtecho itemType表备份已完成%3log.txtbcp SELECT * FROM sportSys.dbo.agenda wheresportSys.dbo.agenda.userId%1 queryout %2agenda.xls -T -c%3log.txtecho agenda表备份已完成%3log.txtbcp SELECT * FROM sportSys.dbo.allroundInfo wheresportSys.dbo.allroundInfo.userId%1 queryout %2allroundInfo.xls -T -c%3log.txtecho allroundInfo表备份已完成%3log.txtbcp SELECT * FROM sportSys.dbo.athlete wheresportSys.dbo.athlete.userId%1 queryout %2athlete.xls -T -c%3log.txtecho athlete表备份已完成%3log.txtexit下面我们来分析下这个批处理bcp SELECT * FROM sportSys.dbo.competitions wheresportSys.dbo.competitions.userId%1 queryout %2competitions.xls -T -c%3log.txtbcp 这个是语法双引号里面写的是Sql语句%1、%2、%3是要传递给bat文件的参数%1表示第一个参数%2表示第二个参数%3表示第三个参数。本人的这三个参数的意思分别是第一个参数查询条件第二个参数导出文件保存的位置第三个参数输出日志保存的位置②Java程序中调用导出文件publicString backUp()throwsException {try{HttpServletRequest request  ServletActionContext.getRequest();HttpServletResponse response  ServletActionContext.getResponse();Map session  ActionContext.getContext().getSession();String userId  session.get(userId).toString();String homeDir1  request.getSession().getServletContext().getRealPath(/);//Runtime.getRuntime().exec(notepad);Runtime.getRuntime().exec(cmd /k start /b homeDir1backUp\\backupBy.bat  userId  homeDir1downloadFile.separatorChar  userIdFile.separatorChar homeDir1downloadFile.separatorChar  userIdFile.separatorChar);}catch(IOException e) {// TODO Auto-generated catch blocke.printStackTrace();returnINPUT;}returnSUCCESS;}Java中调用命令行程序的方式就是第11行Runtime.getRuntime().exec(cmd /k start /b homeDir1backUp\\backupBy.bat  userId  homeDir1downloadFile.separatorChar  userIdFile.separatorChar homeDir1downloadFile.separatorChar  userIdFile.separatorChar);Runtime每个 Java 应用程序都有一个Runtime类实例使应用程序能够与其运行的环境相连接。可以通过getRuntime方法获取当前运行时。应用程序不能创建自己的 Runtime 类实例。public Process exec(String command)throws IOException在单独的进程中执行指定的字符串命令。这是一个很有用的方法。对于 exec(command) 形式的调用而言其行为与调用 exec(command, null, null) 完全相同。参数command - 一条指定的系统命令。返回一个新的 Process 对象用于管理子进程抛出SecurityException - 如果安全管理器存在并且其 checkExec 方法不允许创建子进程IOException - 如果发生 I/O 错误NullPointerException - 如果 command 为 nullIllegalArgumentException - 如果 command 为空另请参见exec(String[], String[], File), ProcessBuilder为了使调用bat文件来运行的时候不至于弹出一个黑框加入/b参数 即可解决③导入bcp sportSys.dbo.competitions in %1competitions.xls -c -t以上便是导入的指令 同样也可以设置将待导入的文件全部放在目录中然后导入即可④压缩成Zip文件-工具类(网上有写好的ZipUtil)packagecom.yaxing.util;importjava.io.BufferedInputStream;importjava.io.File;importjava.io.FileInputStream;importjava.io.FileNotFoundException;importjava.io.FileOutputStream;importjava.io.IOException;importjava.util.jar.JarEntry;importjava.util.jar.JarOutputStream;importjava.util.jar.Manifest;publicclassZipUtil {protectedstaticbyte[] buf newbyte[1024];/*** 私有构造函数防止被构建*/privateZipUtil() {}/*** 遍历目录并添加文件.** param jos*            - JAR 输出流* param file*            - 目录文件名* param pathName*            - ZIP中的目录名* throws IOException* throws FileNotFoundException*/privatestaticvoidrecurseFiles(finalJarOutputStream jos,finalFile file,finalString pathName)throwsIOException,FileNotFoundException {// 文件夹则往下遍历if(file.isDirectory()) {finalString sPathName  pathName  file.getName() /;jos.putNextEntry(newJarEntry(sPathName));finalString[] fileNames  file.list();if(fileNames !null) {for(inti 0; i  fileNames.length; i) {recurseFiles(jos,newFile(file, fileNames[i]), sPathName);}}}// 读取文件到ZIP/JAR文件条目else{// 使用指定名称创建新的 ZIP/JAR 条目finalJarEntry jarEntry newJarEntry(pathName  file.getName());finalFileInputStream fin newFileInputStream(file);finalBufferedInputStream in newBufferedInputStream(fin);// 开始写入新的 ZIP 文件条目并将流定位到条目数据的开始处。jos.putNextEntry(jarEntry);intlen;while((len  in.read(buf)) 0) {// 将字节数组写入当前 ZIP 条目数据jos.write(buf,0, len);}in.close();// 关闭当前 ZIP 条目并定位流以写入下一个条目jos.closeEntry();}}/*** 创建 ZIP/JAR 文件.** param directory*            - 要添加的目录* param zipFile*            - 保存的 ZIP 文件名* param zipFolderName*            - ZIP 中的路径名* param level*            - 压缩级别(0~9)* throws IOException* throws FileNotFoundException*/publicstaticvoidmakeDirectoryToZip(finalFile directory,finalFile zipFile,finalString zipFolderName,finalintlevel)throwsIOException, FileNotFoundException {FileOutputStream fos null;try{// 输出文件流fos newFileOutputStream(zipFile);}catch(finalException e) {// 建立打包后的空文件newFile(zipFile.getParent()).mkdirs();zipFile.createNewFile();fos newFileOutputStream(zipFile);}// 使用指定的 Manifest 创建新的 JarOutputStream。清单作为输出流的第一个条目被写入finalJarOutputStream jos newJarOutputStream(fos,newManifest());jos.setLevel(checkZipLevel(level));finalString[] fileNames  directory.list();if(fileNames !null) {for(inti 0; i  fileNames.length; i) {// 对一级目录下的所有文件或文件夹进行处理recurseFiles(jos,newFile(directory, fileNames[i]),zipFolderName null?: zipFolderName);}}// 关闭 ZIP 输出流和正在过滤的流。jos.close();}/*** 检查并设置有效的压缩级别,避免压缩级别设置错的异常** param level*            - 压缩级别* return 有效的压缩级别或者默认压缩级别*/publicstaticintcheckZipLevel(finalintlevel) {if(level 0|| level 9) {return7;}else{returnlevel;}}publicstaticvoidmain(finalString args[])throwsFileNotFoundException,IOException {// makeDirectoryToZip();finalString homeDir  System.getProperty(user.dir);System.out.println(homeDir);finalFile zipFile newFile(homeDir,download File.separatorChartest.zip);finalFile pagesDirectory newFile(homeDir,src);System.out.println(Making zip file from folder /src to  zipFile);ZipUtil.makeDirectoryToZip(pagesDirectory, zipFile,,9);System.out.println(Zip file  zipFile  has been made.);}}⑤Struts2执行Action里面的方法publicString execute()throwsException {HttpServletRequest request  ServletActionContext.getRequest();HttpServletResponse response  ServletActionContext.getResponse();Map session  ActionContext.getContext().getSession();String userId  session.get(userId).toString();finalString homeDir  request.getSession().getServletContext().getRealPath(/);// 打包后文件的位置及名称finalFile zipFile newFile(homeDir,download File.separatorChar userId  File.separatorChar  userId bak.zip);// 要打包的文件夹路径// if((new File(userId).isDirectory())){// System.out.println(文件夹userId已存在创建失败);// }else{// new File(userId).mkdir();// System.out.println(创建文件夹userId成功);// }finalFile pagesDirectory newFile(homeDir,download/ userId);LOG.info(Making zip file from folder / userId  to  zipFile);// 压缩文件ZipUtil.makeDirectoryToZip(pagesDirectory, zipFile,,9);LOG.info(Zip file  zipFile  has been made.);response.sendRedirect(../download/ userId / userIdbak.zip);returnnull;// return super.execute();}压缩文件创建之后返回该压缩包提供用户下载用户将下载的文件导入客户端系统中即可四、总结本文总结了Java中调用批处理文件给批处理文件传递参数的使用方法。依据此可以实现项目中多种用途的数据备份。欢迎各位交流如有更好的方法欢迎指出谢谢