我知道我们可以使用 Apache POI 来解析 Excel 文件并获取数据。但我听说了一件奇怪的事情,Excel 文件可以以与我们解析 CSV 类似的方式传递(就像从文件流中读取文件并用“逗号”分隔符分隔每个列值)。当我们解析Excel时,我们必须使用制表符作为分隔符。是否可以?如果是的话,那么为什么 Apache 会提出如此复杂的框架呢?我很困惑。有人可以帮助我吗?
CSV 是一种文本格式,因此可以使用分隔符进行解析。旧版 Excel 是一种二进制且专有的格式,因此需要巧妙的解码。新的 Excel 格式是压缩的 XML,但在将其转换为像逐个读取单元格这样简单的内容之前,人们还应该了解该文档的结构。所以你的问题的答案是否定的,你需要使用 Apache POI,而且 - 这没有什么问题。
顺便说一句,在成为一名优秀开发人员的道路上,您需要学会在寻求帮助之前进行一些自己的研究。亲自动手是学习东西的最好方法。
您可能对自己所听到的内容感到困惑,或者告诉您的人也感到困惑。
Excel 文件的某些部分可以(在某种程度上)存储为 CSV 文件,因为表格数据结构非常适合 CSV 文件格式。但是,如果您以 CSV 格式保存,那么您只会在每个单元格中获得纯文本 - 您会丢失所有格式信息、任何图表、多个工作表等。
Apache POI 使用原生 XLS excel 格式,因此可以处理 excel 中的所有内容,而不仅仅是某些单元格中的限制性纯文本。 CSV 文件有其用途,但它们绝对不能直接替代普通 Excel 文件。
我尝试在不使用 POI 等任何外部 JAR 的情况下读取/写入 excel 文件。我能够将文件写入 xls 格式。这是我的代码
FileWriter fwriter = new FileWriter(file,true);
writer = new BufferedWriter(fwriter);
writer.newLine();
writer.write("a" + "\t");
writer.write("b" + "\t");
writer.write("c" + "\t");
writer.write("d" + "\t");
writer.write("e" + "\t");
writer.write("f" + "\t");
读取文件 这是我的阅读代码
if(file != null) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
String line;
while((line = reader.readLine()) != null) {
String[] component = line.split("\\t");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
InputStream is = new FileInputStream(new File(filepath));
StreamingReader reader=null;
try {
reader = StreamingReader.builder()
.rowCacheSize(100)
.bufferSize(4096)
.sheetIndex(0)
.read(is);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}finally{
is.close();
}
//pass here to reader and itrate it
for (Row row : reader) {
if (row.getRowNum()!=0){
for (Cell cell : row) {
// write ur logic to store ur value
}
}
}
遗憾的是,它不像 .csv 文件那样以逗号分隔。 但是,如果您只想从 .xlsx 文件中获取表格内容,而不需要所有花哨的 ApachePOI 内容。您可以使用我的简单解析器:
如何:
fromXLSX
,其中第一个参数是.xlsx文件,第二个参数是excel工作表的名称(保留为空将默认选择第一个工作表)String[#ROWS][#COLUMN]
。免责声明: 仅测试字符串和数字值。不确定它是否适用于公式或日期
public static String[][] fromXLSX(File xlsx, String sheet) {
FileInputStream fis;
try {
fis = new FileInputStream(xlsx);
ZipInputStream zis = new ZipInputStream(fis);
ZipEntry ze = zis.getNextEntry();
LinkedList<CellData> cellDatas = null;
String[] sharedStrings = null;
while(ze != null) {
String fileName = ze.getName();
if ((sheet == null && fileName.contains("worksheets")) || (sheet != null && fileName.endsWith(sheet + ".xml"))) {
cellDatas = cellDataFromXLSXextractedXML(readZipEntryToString(zis));
} else if (fileName.endsWith("sharedStrings.xml")) {
sharedStrings = sharedStringsFromXML(readZipEntryToString(zis));
}
zis.closeEntry();
ze = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
fis.close();
int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE, maxX = 0, maxY = 0;
for(CellData c : cellDatas) {
int x = c.getCol();
int y = c.getRow();
if (x < minX)
minX = x;
if (x > maxX)
maxX = x;
if (y < minY)
minY = y;
if (y > maxY)
maxY = y;
//replace String values
if(c.string) {
c.value = sharedStrings[c.getValueInt()];
}
}
int w = maxX - minX + 1;
int h = maxY - minY + 1;
String[][] values = new String[h][w];
for(CellData c : cellDatas) {
values[c.getRow() - minY][c.getCol() - minX] = c.value;
}
return values;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private static String readZipEntryToString(ZipInputStream zis) throws IOException {
byte[] buffer = new byte[1024];
int len;
StringBuilder xml = new StringBuilder();
while ((len = zis.read(buffer)) > 0) {
String str = new String(buffer, 0, len);
xml.append(str);
}
return xml.toString();
}
private static String[] sharedStringsFromXML(String xml) {
LinkedList<String> res = new LinkedList<>();
int index = 0;
while((index = xml.indexOf("<t>", index)) != -1) {
int end = xml.indexOf("</t>", index);
res.add(xml.substring(index + 3, end));
index = end;
}
return (String[]) res.toArray(new String[res.size()]);
}
private static LinkedList<CellData> cellDataFromXLSXextractedXML(String sheetXml) {
String sheetData = sheetXml.substring(sheetXml.indexOf("<sheetData>") + "<sheetData>".length(), sheetXml.indexOf("</sheetData>"));
LinkedList<CellData> cellData = new LinkedList<>();
int index = 0;
while((index = sheetData.indexOf("<c r=\"", index)) != -1) {
String cellID = sheetData.substring(index + 6, sheetData.indexOf('"', index + 6));
int endOfTag = sheetData.indexOf('>', index);
int typeString = sheetData.indexOf("t=\"s\"", index);
boolean isStr = typeString != -1 && typeString < endOfTag;
int valOpen = sheetData.indexOf("<v>", endOfTag);
int valClose = sheetData.indexOf("</v>", valOpen);
String value = sheetData.substring(valOpen + 3, valClose);
cellData.add(new CellData(cellID, value, isStr));
index = endOfTag;
}
return cellData;
}
private static class CellData {
public String cellID;
public String value;
public boolean string;
public CellData(String cellID, String value, boolean string) {
this.cellID = cellID;
this.value = value;
this.string = string;
}
private int getCol() {
String rev_id = new StringBuilder(cellID).reverse().toString();
int pos = 0;
int sum = 0;
while(Character.isDigit(rev_id.charAt(pos))) {
pos++;
}
int offs = pos;
while(pos < rev_id.length()) {
sum += (((int)rev_id.charAt(pos)) - ((int)'A')) * (powInt(26, pos - offs));
pos++;
}
return sum;
}
private int getRow() {
int pos = 0;
while(!Character.isDigit(cellID.charAt(pos))) {
pos++;
}
return Integer.parseInt(cellID.substring(pos));
}
public int getValueInt() {
return Integer.parseInt(value);
}
private int powInt(int base, int to) {
int res = 1;
for(int i = 0; i < to; i++) {
res *= base;
}
return res;
}
@Override
public String toString() {
return "Cell: [" + getCol() + ", " + getRow() + "]: " + value + " (str: " +string + ")";
}
}