老鬼的博客 来都来啦,那就随便看看吧~
Java读取大数据量的CSV文件
发布于: 2018-07-08 更新于: 2018-10-22 分类于:  阅读次数: 

原理

1
2
3
4
5
6
7
  对于大数据量的CSV文件,不能一下子全部加载出来,要不然会造成内存溢出,要做的就是
将部分的内容放在一定大小的缓冲池中,分批读取,直到读取完毕,首先向将File转换成inputstream
,然后用IoUtils的read方法进行读取,其中遇到的问题就是,加入csv文件中包含了中文,分批
读取的时候可能会将一个中文拆开读取,为了避免这种现象,如果读取到的内容不是以\n结尾,说明
读取到的内容不是整数行,然后将读取到内容分成两段,一段是最后一个\n之前的内容,第二个是剩余
的不到一行的内容,然后将剩余的部分加到下一次的读取中。

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package com.tohours.agent5v5.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.Logger;

public class Test {

private static Logger log = Logger.getLogger(Test.class);

/**
* 加载csv的内容,如果加载的内容此时刚好不够一行,则截取到上一行的末尾,这样加载出来的数据都是整数倍的行数
*
* @param csvPath
*/
public static void loadCsvData(String csvPath) {
try {

File dataFile = new File(csvPath);
byte[] lastByte = {};
Integer length = 94372 * 5;
Boolean isOver = false;
FileInputStream input = new FileInputStream(dataFile);
Map<String, Object> rv = null;
String content = "";
String charset = "GBK";
while (!isOver) {

if (rv != null && rv.containsKey("lastByte")) {
lastByte = (byte[]) rv.get("lastByte");
}
rv = loadContent(length, input, lastByte, charset);
isOver = (Boolean) rv.get("isOver");
content = (String) rv.get("content");
log.info("content:" + content);
}
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 加载inputsteam的数据
*
* @param length
* @param input
* @param last
* @param charset
* @return
* @throws IOException
*/
private static Map<String, Object> loadContent(Integer length,
InputStream input, byte[] la, String charset) throws IOException {
Map<String, Object> rv = new HashMap<String, Object>();
byte[] buffer = new byte[la.length + length];
copyToBuffer(buffer, la);
Integer read = IOUtils.read(input, buffer, la.length, length);
byte hh = 10;// 换行符
int lastN = ArrayUtils.lastIndexOf(buffer, hh);
byte[] conArray = ArrayUtils.subarray(buffer, 0, lastN);
byte[] lastByte = ArrayUtils.subarray(buffer, lastN, buffer.length);
String content = new String(conArray, 0, conArray.length, charset);

rv.put("isOver", read < length);
rv.put("content", content);
rv.put("lastByte", lastByte);
return rv;
}

/**
* copy byte
*
* @param buffer
* @param la
*/
private static void copyToBuffer(byte[] buffer, byte[] la) {
for (int i = 0; i < la.length; i++) {
buffer[i] = la[i];
}
}

public static void main(String[] args) {
String csvPath = "C:\\20180630115435.csv";
loadCsvData(csvPath);
}

}

*************感谢您的阅读*************