Java 按顺序读取行,但按需读取

Java 按顺序读取行,但按需读取,java,excel,apache-poi,Java,Excel,Apache Poi,我需要逐行遍历Excel电子表格,但不是一次遍历全部。我想保持一个流对电子表格开放,然后将该对象传递给另一个方法。此方法将不时请求下一行数据。此方法已建立,因此无法更改 我最初尝试使用XSSFWorkbook,效果非常好,直到实际数据的内存用完 然后,我尝试使用XSSFSheetXMLHandler切换到SAX解析器,使用一个自定义解析器,类似于ApachePOI项目提供的示例解析器XLSX2CSV。但这会导致一次处理所有行;如果我把它们存储在内存中以便以后阅读,我也会耗尽内存。我也不能再访问D

我需要逐行遍历Excel电子表格,但不是一次遍历全部。我想保持一个流对电子表格开放,然后将该对象传递给另一个方法。此方法将不时请求下一行数据。此方法已建立,因此无法更改

我最初尝试使用
XSSFWorkbook
,效果非常好,直到实际数据的内存用完

然后,我尝试使用
XSSFSheetXMLHandler
切换到SAX解析器,使用一个自定义解析器,类似于ApachePOI项目提供的示例解析器
XLSX2CSV
。但这会导致一次处理所有行;如果我把它们存储在内存中以便以后阅读,我也会耗尽内存。我也不能再访问
DataFormatter
,我需要它来处理单元格值


有人能给我举一个例子/类让我做这个吗?

我更喜欢的XML流API是

知道
*.xlsx
文件只是一个
ZIP
存档,而
apache poi
s是一个
ZIP包
,我们可以考虑以下方法:

  • *.xlsx获取
    /xl/worksheets/sheets n.xml
    包部分 Excel
    ZipPackage
  • 在上面创建一个
    StAX
    读卡器
  • 现在,我们可以使用此读取器从
    XML
    中读取
下面的示例创建了一个基本应用程序,该应用程序通过单击按钮逐行执行此操作

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import org.apache.poi.openxml4j.opc.*;

import javax.xml.stream.*;
import javax.xml.stream.events.*;

import javax.xml.namespace.QName;

import java.util.regex.Pattern;

public class GetExcelRowByRow extends JPanel implements ActionListener {
 protected JButton button;
 protected JTextArea textArea;
 private final static String newline = "\n";

 //file path to Excel file and sheet number to work with
 private final static String filepath = "file.xlsx";
 private final static int scheetnr = 1;

 private StaxExcelRowByRowReader reader;

 public GetExcelRowByRow() {
  super(new GridBagLayout());
  button = new JButton("Next Row");
  button.addActionListener(this);
  textArea = new JTextArea(15, 50) {
   @Override
   public boolean getScrollableTracksViewportWidth() {
    return true;
   }
  };
  textArea.setLineWrap(true);
  textArea.setEditable(false);
  JScrollPane scrollPane = new JScrollPane(textArea);
  GridBagConstraints c = new GridBagConstraints();
  c.gridwidth = GridBagConstraints.REMAINDER;
  c.fill = GridBagConstraints.HORIZONTAL;
  add(button, c);
  c.fill = GridBagConstraints.BOTH;
  c.weightx = 1.0;
  c.weighty = 1.0;
  add(scrollPane, c);

  try {
   reader = new StaxExcelRowByRowReader(filepath, scheetnr);
  } catch (Exception ex) {
   ex.printStackTrace();
  }

 }
 @Override
 public void actionPerformed(ActionEvent evt) {
  String row = "Row not found...";
  try {
   row = reader.getNextRow();
  } catch (Exception ex) {
   ex.printStackTrace();
  }
  textArea.append(row + newline);
  textArea.setCaretPosition(textArea.getDocument().getLength());
 }

 public StaxExcelRowByRowReader getReader() {
  return reader;
 }

 private static void createAndShowGUI() {
  JFrame frame = new JFrame("Get Excel row by row");
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  GetExcelRowByRow app = new GetExcelRowByRow();
  frame.add(app);

  frame.addWindowListener(new WindowAdapter() {
   @Override
   public void windowClosing(WindowEvent windowEvent) {
    try {
     app.getReader().close();
    } catch (Exception ex) {
     ex.printStackTrace();
    }
    System.exit(0);
   }
  });

  frame.pack();
  frame.setVisible(true);
 }

 public static void main(String[] args) {
  javax.swing.SwingUtilities.invokeLater(new Runnable() {
   public void run() {
    createAndShowGUI();
   }
  });
 }

 //class for reading a /xl/worksheets/sheetN.xml package part from a *.xlsx Excel ZipPackage 
 private class StaxExcelRowByRowReader {

  private XMLEventReader sheetreader;
  private OPCPackage opcpackage; 

  public StaxExcelRowByRowReader(String filepath, int sheetnr) {
   try {
    opcpackage = OPCPackage.open(filepath, PackageAccess.READ);
    //get the sheet package part
    PackagePart sheetpart = opcpackage.getPartsByName(Pattern.compile("/xl/worksheets/sheet"+sheetnr+".xml")).get(0);
    //create reader for the sheet package part            
    sheetreader = XMLInputFactory.newInstance().createXMLEventReader(sheetpart.getInputStream());
   } catch (Exception ex) {
    ex.printStackTrace();
   }
  }

  //method for getting the next row from the reader
  public String getNextRow() throws Exception {
   StringBuffer row = new StringBuffer();
   boolean valueFound = false;
   boolean nextValueIsSharedString = false;
   while(sheetreader.hasNext()){
    XMLEvent event = sheetreader.nextEvent();
    if(event.isStartElement()) {
     StartElement startElement = (StartElement)event;
     QName startElementName = startElement.getName();
     if(startElementName.getLocalPart().equalsIgnoreCase("row")) { //start element of row
      row.append("<row");
      row.append(" " + startElement.getAttributeByName(new QName("r")));
      row.append(">");
     } else if(startElementName.getLocalPart().equalsIgnoreCase("c")) { //start element of cell
      row.append("<c");
      row.append(" " + startElement.getAttributeByName(new QName("r")));
      row.append(" " + startElement.getAttributeByName(new QName("s")));
      row.append(" " + startElement.getAttributeByName(new QName("t")));
      row.append(">");
      Attribute type = startElement.getAttributeByName(new QName("t"));
      if (type != null && "s".equals(type.getValue())) {
       nextValueIsSharedString = true;
      } else {
       nextValueIsSharedString = false;
      }
     } else if(startElementName.getLocalPart().equalsIgnoreCase("v")) { //start element of value
      row.append("<v>");
      valueFound = true;
     }
    } else if(event.isCharacters() && valueFound) {
     Characters characters = (Characters)event;
     if (nextValueIsSharedString) {
      row.append("shared string: " + characters.getData());
     } else {
      row.append(characters.getData());
     }
    } else if(event.isEndElement()) {
     EndElement endElement = (EndElement)event;
     QName endElementName = endElement.getName();
     if(endElementName.getLocalPart().equalsIgnoreCase("v")) { //end element of value
      row.append("</v>");
      valueFound = false;
     } else if(endElementName.getLocalPart().equalsIgnoreCase("c")) { //end element of cell
      row.append("</c>");
     } else if(endElementName.getLocalPart().equalsIgnoreCase("row")) { //end element of row
      row.append("</row>");
      return row.toString();
     }
    }
   }
   return "No more rows.";
  }

  public void close() throws Exception {
   if (sheetreader != null) sheetreader.close();
   if (opcpackage != null) opcpackage.close();
  }
 }
}
import java.awt.*;
导入java.awt.event.*;
导入javax.swing.*;
导入org.apache.poi.openxml4j.opc.*;
导入javax.xml.stream.*;
导入javax.xml.stream.events.*;
导入javax.xml.namespace.QName;
导入java.util.regex.Pattern;
公共类GetExcelRowByRow扩展了JPanel实现ActionListener{
受保护的按钮;
保护区;
私有最终静态字符串换行符=“\n”;
//Excel文件的文件路径和要使用的图纸编号
私有最终静态字符串filepath=“file.xlsx”;
私有最终静态int scheetnr=1;
专用StaxExcelRowByRowReader;
公共GetExcelRowByRow(){
超级(新GridBagLayout());
按钮=新的JButton(“下一行”);
addActionListener(这个);
textArea=新的JTextArea(15,50){
@凌驾
公共布尔值getScrollableTracksViewportWidth(){
返回true;
}
};
textArea.setLineWrap(true);
textArea.setEditable(false);
JScrollPane scrollPane=新的JScrollPane(textArea);
GridBagConstraints c=新的GridBagConstraints();
c、 gridwidth=GridBagConstraints.rements;
c、 填充=GridBagConstraints.HORIZONTAL;
添加(按钮,c);
c、 fill=GridBagConstraints.BOTH;
c、 权重x=1.0;
c、 权重y=1.0;
添加(滚动窗格,c);
试一试{
reader=new statexcelrowByRowReader(文件路径,scheetnr);
}捕获(例外情况除外){
例如printStackTrace();
}
}
@凌驾
已执行的公共无效操作(操作事件evt){
String row=“未找到行…”;
试一试{
row=reader.getNextRow();
}捕获(例外情况除外){
例如printStackTrace();
}
textArea.append(行+换行符);
textArea.setCaretPosition(textArea.getDocument().getLength());
}
公共StaxExcelRowByRowReader getReader(){
返回读取器;
}
私有静态void createAndShowGUI(){
JFrame=newJFrame(“逐行获取Excel”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GetExcelRowByRow app=新建GetExcelRowByRow();
frame.add(app);
frame.addWindowListener(新的WindowAdapter(){
@凌驾
公共作废窗口关闭(WindowEvent WindowEvent){
试一试{
app.getReader().close();
}捕获(例外情况除外){
例如printStackTrace();
}
系统出口(0);
}
});
frame.pack();
frame.setVisible(true);
}
公共静态void main(字符串[]args){
javax.swing.SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
createAndShowGUI();
}
});
}
//用于从*.xlsx Excel压缩包中读取/xl/worksheets/sheetN.xml包部件的类
私有类StaxExcelRowByRowReader{
私有XMLEventReader sheetreader;
私有OPCPackage OPCPackage;
公共StaxExcelRowByRowReader(字符串文件路径,int sheetnr){
试一试{
opcpackage=opcpackage.open(文件路径,PackageAccess.READ);
//获取板材包装零件
PackagePart sheetpart=opcpackage.getPartsByName(Pattern.compile(“/xl/worksheets/sheet”+sheetnr+“.xml”)).get(0);
//为图纸包零件创建读取器
sheetreader=XMLInputFactory.newInstance().createXMLEventReader(sheetpart.getInputStream());
}捕获(例外情况除外){
例如printStackTrace();
}
}
//从读取器获取下一行的方法
公共字符串getNextRow()引发异常{
StringBuffer行=新的StringBuffer();
布尔值found=false;
布尔值nextValueIsSharedString=false;
while(sheetreader.hasNext()){
XMLEvent事件=sheetreader.nextEvent();
if(event.isStartElement()){
StartElement StartElement=(StartElement)事件;
QName startElementName=startElement.getName();
if(startElementName.getLocalPart().equalsIgnoreCase(“行”){//行的起始元素
行。追加(“”);
}else if(startElementName.getLocalPart().equalsIgnoreCase(“c”){//单元格的起始元素
行。追加(“”);
属性类型=startElement.getAttributeByName(新的QName(“t”);
if(type!=null&&“s”.equals(type.getValue())){
nextValueIsSharedString=true;
}否则{
nextValueIsSharedString=false;
}
}else if(startElementName.getLocalPart().equalsIgnoreCase(“v”){//value的开始元素
行。追加(“”);
valueFound=true;
}
}else if(event.isCharacters()&&valueFound){
字符=(字符)事件;
if(下一个值共享字符串){
append(“共享字符串:+characters.getData());
}否则{
行。追加(字符)