import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.MapUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.huateng.common.service.CommonBaseService;
import com.huateng.common.util.Assert;
import com.huateng.common.util.Constant;
import com.huateng.common.util.DateUtil;
import com.huateng.common.util.StringUtils;
import com.ums.bke.outerdata.settle.createfile.dao.SettleCreateFileDao;
/**
* desc:创建文件
*/
@Service
public class SettleCreateFileService extends CommonBaseService{
@Autowired
private SettleCreateFileDao settleCreateFileDao;
@Override
public SettleCreateFileDao getBaseDao() {
return settleCreateFileDao;
}
/**
* 查询启用的清分文件生成方案
* @return
*/
private Map<String, String> getDisplayInfo(){
return settleCreateFileDao.getDisplayInfo();
}
/**
* 查询清分文件生成所用到的字段
* @return
*/
private List<String> getDisplayField(Object obj){
return settleCreateFileDao.getDisplayField(obj);
}
/**
* 获取清分数据。因数据量可能很大,为方式内存溢出,所以采用分批获取的方式(也就是分页方式)<br/>
* LinkedHashMap是一个有序的map
* @return
* @throws Exception
*/
@SuppressWarnings("unchecked")
private List<LinkedHashMap<String, String>> getSettleInfo(List<String> fieldList, int currentPage) throws Exception{
//组织分页信息
Map map = new HashMap();
map.put("fieldList", fieldList);//要查询的字段
int pageSize = 1000; //批量查询,每批可查询的数据条数
RowBounds bounds = new RowBounds(currentPage * pageSize, pageSize);
return this.settleCreateFileDao.getSettleInfo(map, bounds);
}
/**
* 创建文件
* @throws Exception
*/
public void doCreateFile() throws Exception{
//1 -查询启用的清分文件生成方案
Map<String, String> map = getDisplayInfo();
Assert.isTrue(null!=map && map.size()!=0, "未找到对应的清分文件生成方案!");
log.info("清分文件圣生成方案:" + map);
String fieldSeparator = MapUtils.getString(map, "RESV2", "|"); //字段分隔符,默认分隔符是|
//2 - 根据方案,查询清分文件生成所用到的字段
List<String> fieldList = getDisplayField(map);
Assert.isTrue(null!=fieldList && fieldList.size()!=0, "清分文件生成方案中没有配置查询字段!");
log.info("清分文件要查询的字段:"+ fieldList.size() + fieldList);
//分批次从清分库中获取数据,并写入文件中
String fileName = "selltle_" + DateUtil.getStrDate("yyyyMMddHHmmssSSS") + ".txt.tmp";
FileOutputStream stream = new FileOutputStream(Constant.SETTLE_SAVE_DIR + fileName);
FileChannel channel = stream.getChannel();//根据FileOutputStream获得通道FileChannel
int currentPage = 0;//从0开始计算批次
try {
while (currentPage >= 0) {
log.info("从清分中提取数据,(批次从0开始计算)当前批次currentPage是:" + currentPage);
List<LinkedHashMap<String, String>> settleList = this.getSettleInfo(fieldList, currentPage);// 此处根据currentPage调用service获取数据
if (null != settleList && settleList.size() > 0) {
log.info(String.format("当前输出批次(批次从0开始计算)是:%s, 该批次共有数据%s条!", currentPage, settleList.size()));
for (int i = 0; i < settleList.size(); i++) {
StringBuffer sbf = new StringBuffer();
LinkedHashMap<String, String> linkMap = settleList.get(i);
for (int j = 0; j < fieldList.size(); j++) {
String key = fieldList.get(j);
String value = linkMap.get(key);
sbf.append(fieldSeparator);//分隔符
sbf.append(StringUtils.nvl(value, ""));
}
sbf.deleteCharAt(0).append("\r\n");//去掉首字母的分隔符,并在最后增加换行符
channel.write(ByteBuffer.wrap(sbf.toString().getBytes()));//字节方式写入
}
currentPage++;//取下一批数据
} else {
log.info("准备跳出while循环,(批次从0开始计算)总批是:" + currentPage);
currentPage = -1;//当前批次取到的数据为空,则说明所有数据已取完,并跳出while循环
}
}
log.info("已跳出while循环!");
}catch(Exception e){
channel.write(ByteBuffer.wrap("\r\n".getBytes()));//输出换行
channel.write(ByteBuffer.wrap(StringUtils.getStackTrace(e).getBytes()));//将异常信息输出到文件
//生成文件出错
this.close(channel, stream);
//重命名文件,将文件恢复为error的后缀
this.renameTo(Constant.SETTLE_SAVE_DIR + fileName, Constant.SETTLE_SAVE_DIR + fileName.replaceAll("\\.tmp", ".err"));
throw new Exception("生成清分文件异常,(批次从0开始计算)当前批次:" + currentPage, e);
} finally {
this.close(channel, stream);
}
//重命名文件,将文件恢复为正常的后缀
this.renameTo(Constant.SETTLE_SAVE_DIR + fileName, Constant.SETTLE_SAVE_DIR + fileName.replaceAll("\\.tmp", ""));
log.info("生成清分文件完毕");
}
/**
* 关闭流
* @param channel
* @param stream
* @throws IOException
*/
private void close(FileChannel channel, FileOutputStream stream ) throws IOException{
channel.close();
stream.flush();
stream.close();
log.info("关闭通道,刷新流,生成文件完毕!");
}
/**
* 重命名文件
* @param file
* @param fileTo
* @return
*/
private boolean renameTo(String file, String fileTo){
//重命名文件,将文件恢复为正常的后缀
File temFile = new File(file);
File newFile = new File(fileTo);
boolean brendame = temFile.renameTo(newFile);
log.info(String.format("%s->%s文件重命名结果为:%s", file, fileTo, brendame));
return brendame;
}
}
nio代码片段
最新推荐文章于 2021-02-26 17:19:18 发布