java通过CSV文本格式来导出千万级大数据
Posted robot_sql
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java通过CSV文本格式来导出千万级大数据相关的知识,希望对你有一定的参考价值。
1、由于业务发展,当前页面导出只支持Excel导出数据时间过长已经不能满足系统需要,需要采用导出文本格式的方式来实现业务需求。
JAVA导出文本、mvn打包拒绝访问
NOT all named parameters have been set
java.lang.object无法转换成java.lang.string
2、java导出csv格式方法:
传入参数可以参照自己系统导出Excel的参数
response.setContentType("application/download;charset=UTF-8");
response.setContentType("Content-type:application/vnd.ms-excel;charset=UTF-8");
response.setHeader("Content-disposition","attachment;filename="+java.net.URLEncoder.encode(fileName, "UTF-8"));
outPutStream= response.getOutputStream();
List<HashMap<String,Object>> data = dpservice.getCSVDatalist(tableName, wheresql);
exportResultCSV(data,titleLine.split(","),colmLine.split(","),tableName,outPutStream);
/**
* 导出CSV数据方法
* @param data list集合
* @param titleLine 表头字符串
* @param colmLine SQL列名,用于对应HashMap格式的key来获取值
* @param tableName 表名
* @param outPutStream 输出流
* @throws IOException
*/
public exportResultCSV(List<HashMap<String,Object>> data, String[] titleLine, String[] colmLine,String[] tableName, OutPutStream outPutStream) throws IOException
StringBuffer expStr = new StringBuffer();
try
//csv文件是逗号分隔,除第一个外,每次写入一个单元格数据后需要输入逗号
for(String title : titleLine)
expStr.append(title).append(",");
//写完文件头后换行
expStr.append("\\n");
//写数据
for(HashMap<String,Object> map : data)
//for (String key : map.keySet())
//String val = map.get(key) != null ? map.get(key).toString() : "";
//expStr.append(val).append(",");
//由于HashMap集合里面存储数据属于无序存储,上面的方法属于直接获取,会导致导出的列错位,如下写法规避
for (int j=0,j<colmLine.length;j++)
String val = map.get(colmLine[j].toUppercase()) != null ? map.get(colmLine[j].toUppercase()).toString() : "";
//'\\t'是为了导出格式为文本,避免长串数字变E+科学计数法
expStr.append(val).append("\\t").append(",");
//写完一行换行
expStr.append("\\n");
outPutStream.write(expStr.toString().getBytes("GBK"));
catch (Exception e)
e.printStackTrace();
finally
// 关闭
if(outPutStream != null)
outPutStream.close();
由于上面的导出是放入的字符串,导致导出数据过大的时候会导致java内存溢出,java.lang.OutOfMemoryError :GC ....,所以需要对查询的数据进行分页导出,在mysql中拼接sql时多加个limit pagebeg,pageend的参数设置,内存溢出问题于是解决,新的问题是outPutStream= response.getOutputStream();方式直接浏览器下载只能生成同一个文件,也就是说你的sql结果集被你分成A1.csv,A2.csv,A3.csv,A4.csv时,导出来只有A1.csv,其他数据下载不下来了,由于response.getOutputStream()只响应一次页面,后续response的setHeader数据不会再改变了,不管你循环多少次都是第一份,所以需要将outPutStream= response.getOutputStream();改成outPutStream= new FileOutPutStream("下载路径+文件名+后缀");,这样就可以多份下载了,但是只能下载到你项目部署的服务器,项目部署动态路径如下获取this.getServletContext().getRealPath("/"),如此你就能下载到服务器了。
然后再从服务器通过浏览器将文件下载到到你的个人电脑,通过如下命令即可下载
IOUtils.copy(new FileInputStream("路径+文件名+后缀"),outPutStream) 这样就可以将原先的文件合成一个直接下载到本地了
import org.apache.commons.compress.utils.IOUtils; 用完后记得对IOUtils做close
3、java在拼接sql时,通过传入map参数来实现变量替换(传入方式=:),参数已经传入,直接报错NOT all named parameters have been set ,此错误是由于参数未被解析,需要通过如下代码先行转换:
/**
* 解析替换具名参数
* @param sql 要执行的SQL
* @param paramap 参数map
* @return 替换后的SQL
*/
public String findbySql(String sql, Map<String, object> paramap)
while (sql.indexOf(":") >= 0)
int x_liu = sql.indexOf(":");
int y_liu = sql.substring(x_liu).indexOf(" ");
int e_liu = sql.length();
if (y_liu >= 0)
e_liu = x_liu + y_liu;
String key_liu = sql.substring(x_liu + 1, e_liu);
String value = (String)paramap.get(key_liu); //需要转换下,object无法默认转成string
if (null != value && !"null".equals(value))
value = "'" + value + "'";
sql = sql.substring(0, x_liu) + value + sql.substring(e_liu);
return sql;
另外java.lang.object无法转换成java.lang.string的错误可以参照上面(String)paramap.get(key_liu)的写法。
4、mvn通过命令mvn clean package进行代码打包编译时出现/target/目录“拒绝访问”的错误,这时候需要重启电脑才能对此目录中的文件进行操作,具体原因为文件只有可读权限,需要增加文件夹所有用户(Everyone)所有的控制权限,增加文件加该用户权限自行百度(直接文件夹属性-》安全),不然经常需要重启电脑麻烦的一逼。
以上是关于java通过CSV文本格式来导出千万级大数据的主要内容,如果未能解决你的问题,请参考以下文章