java中实现,在大文件的第一行添加内容

需求描述:

    最近在写一个定时任务,发送多次请求到接口,接口返回报文写入到一个文件中,文件要求格式第一行为总数。这个总数只能在最后的时候才能知道,

这就相当于提出了一个要求:在文件的第一行添加内容,以前的内容整体向下偏移一行。


遇到的问题:

    我开始做的方法是,在代码中 new StringBuffer ,等全部报文返回后,把返回的报文先全部保存到buffer中,用PrintWriter写入总数到文件,再将返回报文写入。可在实际代码运行中,由于每次返回的报文都存入到buffer中,返回的报文对象被buffer对象引用,没有释放掉,所以占用内存很大。折腾了半天不可行。只能换一种思路了。这个文件大小是50多M,内存几百兆没了。

  那既然一次性保存到buffer中不行,那就返回一次报文就保存到本地临时文件中tmpFile,最后在另一个文件dinsFile中先写入总数,从tmpFile没读取一行,就写入到dinsFile。一开始没想到用Scammer这个类,从网上看其他网友的博文才发现正适合,还是很菜,多多学习。

这样占用内存的问题就解决了。下面上代码:

public class QueryBondBalTask extends BaseService{

	private String url;
	private Logger logger = Logger.getLogger(QueryBondBalTask.class);
	public void setUrl(String url) {
		this.url = url;
	}
	
	public void getBondBalToText() {
		
		ICstpCustodianConfigDao cstpCustodianConfigDao = (ICstpCustodianConfigDao) context.getBean("ICstpCustodianConfigDao");
		List<String> list = cstpCustodianConfigDao.selectCustodianAccount();
		// 创建输出临时文件 
		String date = DateTimeClass.getCurDate();
		String name = "tmp_bond_subject_csbs_" + date + "_.txt";
		String tmpPath = FppTradeConfig.ReadStringFromConfig("QueryBondBalTask.tmpPath");
		File tmpFile = new File(tmpPath + name);
		
		//中债登的接口包
		DClient dClient = new DClient(url);
		SAXReader saxReader = new SAXReader();
		
		long sum = 0;
		Reader reader = null;
		PrintWriter pw = null;
		
		try {
			pw = new PrintWriter(tmpFile);
			
			for (String bondId : list) {
				// 模拟请求报文
				String  requestXml = createXml(bondId);
				// 调用接口查询
				String backMsg = dClient.sendMsg(requestXml);

				if (backMsg == null || "" == backMsg) {
					logger.error("返回报文异常", new Exception());
				}
				//解析返回backMsg,生成临时文件
				InputStream input1 = new ByteArrayInputStream(backMsg.getBytes());
				reader = new InputStreamReader(input1);
				Document document = saxReader.read(reader);
				Element root = document.getRootElement();
				// 获取债券账号
				Node accountNode = root.selectSingleNode("//Id");
				String account = accountNode.getText();
				// 余额条数
				List acctLdgList = root.selectNodes("//AcctLdg");
				int size = acctLdgList.size();
				// 获取所有<Bd>标签
				List<Element> bdList = root.selectNodes("//Bd");
				
				for (Element bond : bdList) {
					Node bdidNode = bond.selectSingleNode("BdId");
					String bdid = bdidNode.getText();
					// 从当前节点下获取<AcctLdg>
					List<Element> acctLdglList = bond.selectNodes("SummryStmt/AcctLdg");
		
					for (Element acctLdg : acctLdglList) {
						Node ldgTpnNode = acctLdg.selectSingleNode("LdgTp");
						String ldgTp = ldgTpnNode.getText();
						Node balNode = acctLdg.selectSingleNode("Bal");
						String bal = balNode.getText();
						String record = account + "|" + bdid + "|" + ldgTp + "|" + bal;
						pw.println(record);
					}
				}
				
				pw.flush();
				sum = sum + size;
			}
			//将总数写入文件
			WriteSum(sum,tmpFile);
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			logger.error("中债登接口调用异常", e);
		} catch (DocumentException e) {
			e.printStackTrace();
			logger.error("", e);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("返回报文异常", e);
		} finally{
			if (pw != null) {
				pw.close();
			}
			
			tmpFile.delete();
			
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private String createXml(String bondId) {
		
		String appPath = FppCommMethod.getAPP_HOME();
		String path=appPath + "/config/request.xml";
		File file = new File(path);

		SAXReader saxReader = new SAXReader();
		Document document = null;
		try {
			document = saxReader.read(file);
		} catch (DocumentException e) {
			e.printStackTrace();
			logger.error("", e);
		}
		
		Element root = document.getRootElement();

		Node txFlowIdNode = root.selectSingleNode("//TxFlowId");
		String txFlowId = SequenceCreater.getReconTxFlowID();
		txFlowIdNode.setText(txFlowId);

		Node creDtNode = root.selectSingleNode("//CreDtTm");
		String CreDtTmDate = DateTimeClass.getCurFormatTime();
		creDtNode.setText(CreDtTmDate);
		
		Node startNode = root.selectSingleNode("//StartDt");
		String startDate = DateTimeClass.getCurFormatDate();
		startNode.setText(startDate);
		
		Node endNode = root.selectSingleNode("//EndDt");
		String endDate = DateTimeClass.getCurFormatDate();
		endNode.setText(endDate);

		Node idNode = root.selectSingleNode("//Id");
		idNode.setText(bondId);

		String requestXml = document.asXML();
		return requestXml;
	}

	//读取文件,将总数写入
	private void WriteSum(long sum, File tmpFile) {
		// 最终文件
		String date = DateTimeClass.getCurDate();
		String name = "bond_subject_csbs_" + date + ".txt";
		String destPath = FppTradeConfig.ReadStringFromConfig("QueryBondBalTask.destPath");
		File file = new File(destPath + name);
	
		PrintWriter pw = null;
		Scanner scanner = null;
		InputStream input = null;
		try {
			//输出到最终文件
			pw = new PrintWriter(file);
			pw.println(sum);
			//读取临时文件
			input = new FileInputStream(tmpFile);
			scanner = new Scanner(input);
			
			while (scanner.hasNextLine()) {
				String line = scanner.nextLine();
				pw.println(line);
			}
			pw.print("END");
			pw.flush();
			
		} catch (FileNotFoundException e) {
			logger.error("",e);
		} finally{
			if (scanner != null) {
				scanner.close();
			}
			if (pw != null) {
				pw.close();
			}
			if (input != null) {
				try {
					input.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}


  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值