指定时间段从服务器txt文件中获取指定的数据并下载

本文探讨了一种避免使用IO操作逐个检查FTP服务器历史文件以查找特定数据的方法。通过编写脚本,根据指定日期范围直接在服务器上生成所需文件,从而提高效率并减少FTP连接中断的问题。在Java代码中,使用Runtime类执行shell命令来运行脚本,确保文件生成后再进行下载。此外,还介绍了如何处理文件不存在的情况,并提供了错误处理机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前文
因数据库数据是每日从某一台服务器上的ftp上获取,而经过处理后会产生一些历史数据保留在服务器上,而测试服务在另外一个服务器
需求
在指定时间段内从这些历史数据中查询出来对应的某一条数据,并下载下来;如果使用IO操作的话,会获取所有文件,一次io便利判断是否相等存在,再io,服务器上每天十三个地市,三个月近千,每个文件大小80M左右,这样的话会很慢,且在连接ftp进行IO的过程中,ftp端口占用情况及连接中断各种问题会出现,及网络传输Socket 也可能会中断影响,所以这种方式完全不适合。
另一种想法就是通过命令直接产生需要的文件,再将此文件下载来来,这样在代码中不会一直进行ftp连接及IO操,这样就需要在代码中根据自己的条件产生对应的xshell命令,然后在执行该命令。但是服务器与文件服务器不在同一台上面,因权限,端口开放等问题,最后写个服务放在文件服务器上,并开放某个端口进行调用
这里使用到一些命令 如从某个文件中查询出对应某条数据并写入txt文件cat 20211015北京3.txt |grep 123456 >> 北京_123465.txt
数据格式如图一
在这里插入图片描述
如果在指定时间段内挨个文件查询出对应数据的数据呢,这里使用到一个脚本,自行参考

startDate=20210801;endDate=20211005;startSec=`date -d "$startDate" "+%s"`;endSec=`date -d "$endDate" "+%s"`;for((i=$startSec;i<=$endSec;i+=86400)); do     yd=`date -d "@$i" "+%Y%m%d"`;     cat ${yd}*.txt | grep 123456 >> test.txt ; done


startDate=20210901
endDate=20211005
startSec=`date -d "$startDate" "+%s"`
endSec=`date -d "$endDate" "+%s"`
for((i=$startSec;i<=$endSec;i+=86400))
do
    yd=`date -d "@$i" "+%Y%m%d"`
    cat ${yd}*.txt | grep * >> *.txt 
done 

注:在执行此命令的时候,不存的文件会自行过滤,如下图
在这里插入图片描述
妈的上传图片上传半小时 ,果断不上传了 贴代码 不说了

package com.jshx.zq.p2p.controller;

import com.alibaba.fastjson.JSON;
import com.jshx.zq.p2p.util.DateUtils;
import com.jshx.zq.p2p.util.ResponseBox;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

/**
 * @author xyg
 * @Description 专线号统计导出
 * @Date 2021/10/14 9:19
 */
@Slf4j
@RestController
@RequestMapping("/flow")
public class FlowController {

    /**
     * 根据专线号获取对应的历史流量数据里面的专线号数据
     * @param accessNumber
     * @param month
     * @param city
     * @param type 0 互联网 1 组网
     * @param request
     * @param response
     */
    @GetMapping("/downloadAccessNumber")
    public ResponseBox downloadAccessNumber(@RequestParam(value = "accessNumber",required = false) String accessNumber,
                                            @RequestParam(value = "month",required = false) String month,
                                            @RequestParam(value = "day",required = false) String day,
                                            @RequestParam(value = "city",required = false) String city,
                                            @RequestParam(value = "type",required = false) String type,
                                            @RequestParam(value = "startTime",required = false) String startTime,
                                            @RequestParam(value = "endTime",required = false) String endTime,
                                            HttpServletRequest request, HttpServletResponse response) throws IOException {
        log.info("downloadAccessNumber ======> 据专线号获取对应的历史流量数据里面的专线号数据:accessNumber {}", accessNumber+" month "+month+" city "+city+" type "+type+" startTime "+startTime+" endTime "+endTime);
        ResponseBox responseBox = new ResponseBox();
        String yesterday = DateUtils.getYesterday();
        String[] split = yesterday.split("-");
        String year = split[0];
        String fileName ="历史流量数据";
        StringBuffer commond = new StringBuffer();
        List<String> files = new ArrayList<>();
        List<String> cpath = new ArrayList<>();
        if(month ==null || "".equals(month) || month.equals("null")){
            month = split[1];
        }
        if(day ==null || "".equals(day) || day.equals("day")){
            day = split[2];
        }else{
            if("0".equals(day)) {
                day = "*";
            }
        }
        if(type !=null && !"".equals(type) && !!type.equals("type")){
           if("1".equals(type)){
               type = "组网";
           }else{
               type ="";
           }
        }else{
            type="";
        }
        if(city ==null || "".equals(city) || city.equals("city")){
            if(!"*".equals(day)){
                city = "*";
            }
        }
        commond.append(" "+year);
        commond.append(month);
        commond.append(day);
        commond.append(type);
        commond.append(city);
        commond.append("3.txt");
        if(accessNumber!=null && !"".equals(accessNumber)&&!"null".equals(accessNumber)) {
            commond.append(" | grep " + accessNumber + " >> ");
            fileName = fileName+".txt";
            commond.append(fileName);
            cpath.add(commond.toString());
        }else{
            String com = commond.toString();
            fileName = fileName+".tar";
            String str = fileName+" "+com;
            cpath.add(str);
        }
        if(startTime!=null && !"".equals(startTime)&&!"null".equals(startTime)
           && endTime!=null && !"".equals(endTime)&&!"null".equals(endTime)) {
            fileName = "历史专线数据_"+accessNumber+".txt";
            String commods = "startDate="+startTime+";endDate="+endTime+";startSec=`date -d \"$startDate\" \"+%s\"`;endSec=`date -d \"$endDate\" \"+%s\"`;for((i=$startSec;i<=$endSec;i+=86400)); do     yd=`date -d \"@$i\" \"+%Y%m%d\"`;     cat ${yd}*"+city+"3.txt | grep "+accessNumber+" >> "+fileName+" ; done";
            cpath.clear();
            cpath.add(commods);
        }
        files.add(fileName);
        ServletOutputStream out = null;
        FileInputStream ips = null;
        try {
            Runtime SYS_RUN = Runtime.getRuntime();
            if(startTime!=null && !"".equals(startTime)&&!"null".equals(startTime)
                    && endTime!=null && !"".equals(endTime)&&!"null".equals(endTime)) {
                log.info("据专线号获取对应的历史流量数据里面的专线号数据 commod "+cpath.get(0));
                Process exec = SYS_RUN.exec(new String[]{"sh", "-c", cpath.get(0)});
                exec.waitFor();
            }else if(accessNumber!=null && !"".equals(accessNumber)&&!"null".equals(accessNumber)) {
                log.info("据专线号获取对应的历史流量数据里面的专线号数据 commod "+ "cat "+cpath.get(0));
                Process exec = SYS_RUN.exec(new String[]{"sh", "-c", "cat " + cpath.get(0)});
                //SYS_RUN.exec 执行该命令时主线程会forck一个子进程,子进程是独立的一个执行实体,会导致主进程继续执行,而子进程的命令尚未执行完毕,文件未生成,
                // 进而会出现FileNotFoundException
                //waitFor() 阻塞当前主进程正在执行的线程直到子进程返回,主进程才会继续执行
                exec.waitFor();
            }else{
                log.info("据专线号获取对应的历史流量数据里面的专线号数据 commod "+ "tar -zcvf  "+cpath.get(0));
                Process exec = SYS_RUN.exec(new String[]{"sh", "-c", "tar -zcvf " + cpath.get(0)});
                exec.waitFor();
            }
            String path ="/home/vsftpd/zqftp/lljk/";
            String abosPath = path +fileName;
            File file = new File(abosPath);
            ips = new FileInputStream(file);
            response.setContentType("application/*;charset=UTF-8");
            fileName = URLEncoder.encode(fileName, "UTF-8");
            //为文件重新设置名字,采用数据库内存储的文件名称
            response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
            out = response.getOutputStream();
            //读取文件流
            int len = 0;
            byte[] buffer = new byte[1024 * 10];
            while ((len = ips.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            out.flush();
            responseBox.setSuccess(true);
            responseBox.setMsg("使用命令获取专线号对应的历史流量成功");
            responseBox.setResponseCode(200);
        } catch (Exception e) {
            log.info("执行命令 "+JSON.toJSONString(cpath.get(0))+" 失败");
            responseBox.setSuccess(false);
            responseBox.setMsg("使用命令获取专线号对应的历史流量失败");
            responseBox.setResponseCode(500);
            e.printStackTrace();
        } finally {
            if (out != null) {
                out.close();
            }
            if (ips != null) {
                ips.close();
            }
            removeDir(files);
        }
        return responseBox;
    }


    private static void removeDir(List<String> paths) {
        Runtime SYS_RUN = Runtime.getRuntime();
        for (String path : paths) {
            try {
                SYS_RUN.exec(new String[]{"sh", "-c", "rm -rf " + path});
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

这里需要注意的就是在使用

 Process exec = SYS_RUN.exec(new String[]{"sh", "-c", cpath.get(0)}
 exec.waitFor();

一定要使用 waitFor 因为
SYS_RUN.exec 执行该命令时主线程会forck一个子进程,子进程是独立的一个执行实体,会导致主进程继续执行,而子进程的命令尚未执行完毕,文件未生成,
进而会出现FileNotFoundException
waitFor() 阻塞当前主进程正在执行的线程直到子进程返回,主进程才会继续执行

最后,不想说了 网不好,图片上传不了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值