记一篇I/O流的操作、FTPClient使用、压缩流中ZipInputStream,ZipOutputStream对文件压缩解压操作、压缩文件目录存在中文报错的处理

package com.web.util;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import java.io.*;
import java.util.Enumeration;
import java.util.Set;
import java.util.zip.*;

public class FtpUtil {

    public static final String ENCODING_DEFAULT = "UTF-8";
    public static final String ENCODING_GBK = "GBK";
    public final static Integer BUFFER_SIZE_DEFAULT = 1024;

    /**
     * 描述:将Ftp上文件夹打包成.zip文件
     * @param ftp ftp
     * @param ftpPath ftp文件夹目录
     * @param zipFilePath .zip文件目录 可以是本地或服务器
     * @param fNameSet  Ftp文件夹中需要压缩的文件名称Set集合
     * @return
     */
    public static void zipFile(FTPClient ftp, String  ftpPath, String zipFilePath, Set<String> fNameSet)
            throws IOException
    {
        //创建zip输出流
        ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFilePath));
        // 转移到FTP服务器目录
        ftp.changeWorkingDirectory(ftpPath);
        // 将目录下所有文件、文件夹取出压缩
        FTPFile[] fs = ftp.listFiles();
        for (FTPFile f : fs) {
            compress(zipOut, ftp, f, f.getName(), ftpPath, fNameSet);
        }
        FtpUtil.closeFtp(ftp);
    }

    public static void compress(ZipOutputStream out, FTPClient ftp, FTPFile sourceFile, String base, String workingDirectory, Set<String> fNameSet)
    throws IOException
    {
        //如果路径为目录(文件夹)
        if(sourceFile.isDirectory()) {
            //取出文件夹中的文件(或子文件夹)
            workingDirectory = workingDirectory + File.separator + sourceFile.getName();
            // change working Directory
            ftp.changeWorkingDirectory(workingDirectory);
            FTPFile[] flist = ftp.listFiles();
            out.putNextEntry(new ZipEntry(base + File.separator));
            // 如果文件夹不为空,则递归调用compress,文件夹中的每一个文件(或文件夹)进行压缩
            for (FTPFile ftpFile : flist) {
                compress(out, ftp, ftpFile, base + File.separator + ftpFile.getName(), workingDirectory, fNameSet);
            }
        } else {
            // 只对文件名处理  若文件名存在set集合中就进行压缩 否则就不压
            if(fNameSet.isEmpty()||fNameSet.contains(sourceFile.getName())){
                out.putNextEntry(new ZipEntry(base));
//                    ByteArrayOutputStream os = new ByteArrayOutputStream();
                String downFileName = new String(sourceFile.getName().getBytes("GBK"), "ISO-8859-1");
                ftp.changeWorkingDirectory(workingDirectory);
                ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
//                    ftp.retrieveFile(downFileName, os);
//                    byte[] bytes = os.toByteArray();
//                    InputStream ins = new ByteArrayInputStream(bytes);
                InputStream ins = ftp.retrieveFileStream(downFileName);
                int len;
                byte[] buf = new byte[1024];
                while((len=ins.read(buf, 0, 1024)) != -1) {
                    out.write(buf, 0, len);
                }
               ins.close();
            }
        }
        out.flush();
    }


    /**
     * 描述 : 读取FTP上文件中内容文件中json数据
     * @param ftp
     * @param fileName
     * @param ftpDir
     * @return
     */
    public static String readFileContentFromFtp(FTPClient ftp, String fileName, String ftpDir) throws IOException {
        StringBuffer Contents = new StringBuffer("");
        ftp.changeWorkingDirectory(ftpDir);
        InputStream is = ftp.retrieveFileStream(fileName);
        BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
        String readContentLine = null;
        // 一次读入一行,直到读入null为文件结束
        while ((readContentLine = reader.readLine()) != null) {
            Contents.append(System.lineSeparator() + readContentLine);
        }
        // 关闭reader
        reader.close();
        is.close();
        return Contents.toString();
    }


    /**
     *  描述:将本地文件夹上传至ftp
     * @param ftp
     * @param file 本地文件夹、文件
     * @param remotePath Ftp目录
     */
    public void putDirectoryToFtp(FTPClient ftp, File file, String remotePath){
        try{
            ftp.changeWorkingDirectory(remotePath);
            File[] files = file.listFiles();
            for (File f : files) {
                doMethodPut(ftp, f, remotePath);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public void doMethodPut(FTPClient ftp, File file, String  remotePath){
        try{
            if(file.isDirectory()){
                // 判断ftp是否存在此文件夹,否则就要创建此文件夹。
                String workingSpace = remotePath + file.getName() + File.separator;
                ftp.changeWorkingDirectory(remotePath);
                if(!ftp.changeWorkingDirectory(workingSpace)){
                    ftp.makeDirectory(file.getName());
                }
                File[] tfs = file.listFiles();
                for(File f1 : tfs) {
                    doMethodPut(ftp, f1, workingSpace);
                }
            }else{
                // 切换目录
                ftp.changeWorkingDirectory(remotePath);
                ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
                ftp.storeFile(file.getName(), new FileInputStream(file));
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    /**
     * 描述:删除FTP上文件夹
     * @param ftp ftp
     * @param remotePath Ftp文件夹目录
     */
    private static void delFtpFolder(FTPClient ftp, String remotePath) throws IOException {
        if(ftp.changeWorkingDirectory(remotePath)){
            FTPFile[] files = ftp.listFiles();
            for (FTPFile file : files) {
                doMethodDel(ftp, file, remotePath);
            }
        }

    }

    private static void doMethodDel(FTPClient ftp, FTPFile file, String remotePath) throws IOException {
        if(file.isDirectory()){
            if(null == file){
                ftp.deleteFile(file.getName());
            }else{
                String workingSpace = remotePath + file.getName() + File.separator;
                ftp.changeWorkingDirectory(workingSpace);

                FTPFile[] tfs = ftp.listFiles();
                for(FTPFile f1 : tfs) {
                    doMethodDel(ftp, f1, workingSpace);
                }
            }
            ftp.changeWorkingDirectory(remotePath);
            ftp.removeDirectory(file.getName());
        }else {
            ftp.changeWorkingDirectory(remotePath);
            ftp.deleteFile(file.getName());
        }
    }

    // 上传文件到 服务器
    public static void putFileToServer(InputStream is, String serviceFilePath)
        throws IOException
    {
        OutputStream os  = new FileOutputStream(serviceFilePath);
        byte[] b = new byte[BUFFER_SIZE_DEFAULT];
        int c = 0 ;
        while ( (c = is.read(b)) != -1 ) {
            os.write(b,0,c);
            os.flush();
        }
        os.flush();
        os.close();
    }


    /**
     *  描述:在服务器上 解压.zip文件,
     *  不能解决压缩包中文件夹或文件名称为中文的场景,就是zipIs.getNextEntry() 读到的是中文会直接抛异常。
     *  所以将方法修改为 org.apache.tools.zip.ZipEntry 含有中文的压缩包解压使用ApacheAntUtilUnZip方法。
     * @param zipFilePath
     * @param extPlace
     * @throws IOException
     */
    public static void extZipFileOnService(String zipFilePath, String extPlace) throws IOException {
         FileInputStream is = new FileInputStream(new File(zipFilePath));
         ZipInputStream zipIs = new ZipInputStream(is);
         ZipEntry entry = null;
         while ((entry = zipIs.getNextEntry()) != null){
             String entryName = entry.getName();
//                 System.out.println("entryName= "+ entryName);
            if (entryName.endsWith("/")||entryName.endsWith("\\")||entry.isDirectory()) {
                File file = new File(extPlace + entryName);
                file.mkdirs();
            } else {
                FileOutputStream os = new FileOutputStream(extPlace + entryName);
                // Transfer bytes from the ZIP file to the output file
                byte[] buf = new byte[BUFFER_SIZE_DEFAULT];
                int len;
                while ((len = zipIs.read(buf, 0, buf.length)) > 0) {
                    os.write(buf, 0, len);
                }
                // 关闭流
                os.close();
            }
         }
        is.close();
        zipIs.close();
    }

    public static void ApacheAntUtilUnZip(String zipFilePath, String storePath)
            throws IOException {
        ApacheAntUtilUnZip(new File(zipFilePath), storePath);
    }

    public static void ApacheAntUtilUnZip(File zipFile, String storePath) throws IOException
    {
        if (new File(storePath).exists()) {
            new File(storePath).delete();
        }
        new File(storePath).mkdirs();
        org.apache.tools.zip.ZipFile zip = new org.apache.tools.zip.ZipFile(zipFile, ENCODING_GBK);
        Enumeration<? extends org.apache.tools.zip.ZipEntry> enumeration =
                (Enumeration<org.apache.tools.zip.ZipEntry>) zip.getEntries();
        while (enumeration.hasMoreElements())
        {
            org.apache.tools.zip.ZipEntry zipEntry = (org.apache.tools.zip.ZipEntry)enumeration.nextElement();
            if (!zipEntry.isDirectory()) {
//                System.out.println("文件:"+ zipEntry.getName());
                String zipEntryName = zipEntry.getName();
                if (zipEntryName.indexOf(File.separator) > 0) {
                    String zipEntryDir = zipEntryName.substring(0, zipEntryName.lastIndexOf(File.separator) + 1);
                    String unzipFileDir = storePath + File.separator + zipEntryDir;
                    File unzipFileDirFile = new File(unzipFileDir);
                    if (!unzipFileDirFile.exists()) {
                        unzipFileDirFile.mkdirs();
                    }
                }
                InputStream is = zip.getInputStream(zipEntry);
                FileOutputStream fos = new FileOutputStream(new File(storePath + File.separator + zipEntryName));
                byte[] buff = new byte[BUFFER_SIZE_DEFAULT];
                int size;
                while ((size = is.read(buff, 0, buff.length)) > 0) {
                    fos.write(buff, 0, size);
                }
                fos.flush();
                fos.close();
                is.close();
            }
        }
    }


    /**
     * 描述: 从ftp上下载文件(至本地、服务器)
     * @param ftpClient ftp
     * @param ftpFilePath ftp文件所在目录
     * @param osPath 压缩包地址
     * @param fileName  要下载的文件名称
     *                  修改记录:1.提高下载时效, 将下载方法FTPClient 的.retrieveFile 修改为ftpClient.retrieveFileStream
     */
    public static void downLoadFileFromFtp(FTPClient ftpClient, String ftpFilePath, String osPath, String fileName)
            throws IOException
    {
        InputStream inputStream = null;
        OutputStream os = null;
        os = new FileOutputStream(osPath);
        ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
        // 开启远程被动 传输数据
        ftpClient.enterLocalPassiveMode();
        if (ftpClient.changeWorkingDirectory(ftpFilePath)) {
//                FTPFile[] ftpFiles = ftpClient.listFiles();
//                for (int i = 0; i < ftpFiles.length; i++) {
//                    if(fileName.equals(ftpFiles[i].getName())){
//                        ftpClient.retrieveFile(new String(ftpFiles[i].getName().getBytes("GBK"),"ISO-8859-1"), os);
//                        os.flush();
//                        break;
//                    }
//                }
            inputStream = ftpClient.retrieveFileStream(new String(fileName.getBytes("GBK"), "ISO-8859-1"));
            byte[] buf = new byte[BUFFER_SIZE_DEFAULT];
            int len;
            while ((len = inputStream.read(buf, 0, buf.length)) > 0) {
                os.write(buf, 0, len);
            }
            inputStream.close();
        }
        os.close();
    }


    /**
     *  描述:将目标文件(本地、服务器)上传至ftp
     * @param filePath  目标文件全路径
     * @param ftpFilePath  Ftp目录
     * @param fileName  文件名称
     */
    public static void uploadFile2Ftp(FTPClient ftpClient, String filePath, String ftpFilePath, String fileName)
            throws IOException
    {
           FileInputStream is = new FileInputStream(new File(filePath));
            // 开启远程被动传输模式
//            ftpClient.enterRemotePassiveMode();
            // 切换目录
            ftpClient.changeWorkingDirectory(ftpFilePath);
            ftpClient.setControlEncoding(ENCODING_GBK);
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
            conf.setServerLanguageCode("zh");
            ftpClient.storeFile(fileName, is);
            is.close();
    }

 // 从新压缩 返回给移动端
    private static void buildZip(String fDirectory, String newZipFilePath, Set needZipSet) throws IOException {
        ZipOutputStream zipOutputStream = null;
        zipOutputStream = new ZipOutputStream(new FileOutputStream(new File(newZipFilePath)));
        File file = new File(fDirectory);
        File[] files = file.listFiles();
        if (files != null) {
            for (File f : files) {
                buildZipOut(zipOutputStream, f, f.getName(), needZipSet);
            }
        }
        zipOutputStream.close();

    }

    public static void buildZipOut(ZipOutputStream zipOutputStream, File file, String base, Set needZipSet) throws IOException {
        if (file.isDirectory()) {
            File[] files = file.listFiles();
//                if (files.length == 0) {
//                    zipOutputStream.putNextEntry(new ZipEntry(base + File.separator));
//                } else {
//                    for (int i = 0; i < files.length; i++) {
//                        buildZipOut(zipOutputStream, files[i], base + File.separator + files[i].getName(), needZipSet);
//                    }
//                }
            zipOutputStream.putNextEntry(new ZipEntry(base + File.separator));
            if (files != null) {
                for (File f : files) {
                    buildZipOut(zipOutputStream, f, base + File.separator + f.getName(), needZipSet);
                }
            }
        } else {
            if (needZipSet.isEmpty() || needZipSet.contains(file.getName())) {
                zipOutputStream.putNextEntry(new ZipEntry(base));
                InputStream is = new FileInputStream(file);
                int len;
                byte[] bytes = new byte[1024];
                while ((len = is.read(bytes, 0, 1024)) != -1) {
                    zipOutputStream.write(bytes, 0, len);
                }
                is.close();
            }
        }
    }



    public static void closeFtp(FTPClient ftp){
        try {
            ftp.logout();
            ftp.disconnect();
            System.out.println("FtpBean logout...");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (ftp.isConnected()) {
                try {
                    ftp.logout();
                    ftp.disconnect();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static FTPClient connectFTP(String ip, int port, String userName, String password)
    {
        try{
            FTPClient ftp = new FTPClient();
            ftp.connect(ip, port);
            //下面三行代码必须要,而且不能改变编码格式
            ftp.setControlEncoding(ENCODING_GBK);
            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
            FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
            conf.setServerLanguageCode("zh");
            //如果采用默认端口,可以使用ftp.connect(url) 的方式直接连接FTP服务器
            ftp.login(userName, password);//登录
            System.out.println("FtpBean login success...");
            int reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return null;
            }
            return ftp;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

}
发布了49 篇原创文章 · 获赞 19 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/shenju2011/article/details/97783196