проблемы чтения значений ячеек Excel с использованием Java SAX Parser - PullRequest
0 голосов
/ 03 июня 2019

Я новичок в SAX-разборе и имею небольшой опыт использования библиотек Apache POI в прошлом. У меня есть файл Excel в указанном ниже формате. Это огромный файл размером 10-20 МБ, и я хочу прочитать его, используя SAX Api на Java. Сначала я начал с подхода XSSFWorkbook, но затем переключился на синтаксический анализ SAX из-за серии исключений памяти, возникающих в подходе чтения XSSF.

Однако теперь я застрял как неспособный понять, как получить значение ячейки, используя SAX-разбор. Вот мой код ниже:

Excel_Data.xlsx:

Title    | Label A  | Label B  | Label C 

Signal 1 | value A1 | value B1 | value C1
Signal 2 | value A2 | value B2 | value C2
Signal 3 | value A3 | value B3 | value C3

Функция извлечения данных:

public void executeExcelDataExtraction() throws IOException, 
    OpenXML4JException, SAXException, ParserConfigurationException {

    OPCPackage pkg = OPCPackage.open(XLSX_FILE_PATH);
    XSSFReader r = new XSSFReader( pkg );
    SharedStringsTable sst = r.getSharedStringsTable();
    XMLReader parser = fetchSheetParser(sst);
    Iterator<InputStream> sheets = r.getSheetsData();
    InputStream sheet2 = r.getSheet("rId2");
    InputSource sheetSource = new InputSource(sheet2);
    parser.parse(sheetSource);
    ContentHandler handler = (ImportArticleDataSheetHandler) 
    parser.getContentHandler();
    sheet2.close();
}

Функция XMLReader:

public XMLReader fetchSheetParser(SharedStringsTable sst) throws 
    SAXException, ParserConfigurationException {

    SAXParserFactory factory=SAXParserFactory.newInstance();
    SAXParser parser = factory.newSAXParser();
    XMLReader xmlReader = parser.getXMLReader();
    ContentHandler handler = new ImportArticleDataSheetHandler(sst);
    xmlReader.setContentHandler(handler);
    return xmlReader;
}

ImportArticleDataSheetHandler.java

public class ImportArticleDataSheetHandler extends DefaultHandler{

    private static final String ROW_EVENT = "row";
    private static final String CELL_EVENT = "c";

    private SharedStringsTable sst;
    private String lastContents;
    private boolean nextIsString;

    private List<String> cellCache = new LinkedList<>();
    private List<String[]> rowCache = new LinkedList<>();

    ImportArticleDataSheetHandler(SharedStringsTable sst) {
        this.sst = sst;
    }

    public void startElement(String uri, String localName, String name,
            Attributes attributes) throws SAXException {
        // c => cell
        if (CELL_EVENT.equals(name)) {
            String cellType = attributes.getValue("t");
            if(cellType != null && cellType.equals("s")) {
            nextIsString = true;
            } else {
            nextIsString = false;
            }
        } else if (ROW_EVENT.equals(name)) {
            if (!cellCache.isEmpty()) {
            rowCache.add(cellCache.toArray(new String[cellCache.size()]));
            }
            cellCache.clear();
        }

        // Clear contents cache
        lastContents = "";
    }

    public void endElement(String uri, String localName, String name)
            throws SAXException {
        // Process the last contents as required.
        // Do now, as characters() may be called more than once
        if(nextIsString) {
            int idx = Integer.parseInt(lastContents);
            lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
            nextIsString = false;
        }

        // v => contents of a cell
        // Output after we've seen the string contents
        if(name.equals("v")) {
            cellCache.add(lastContents);
        }
    }

    public void characters(char[] ch, int start, int length)
            throws SAXException {
        lastContents += new String(ch, start, length);
    }

    public List<String[]> getRowCache() {
        return rowCache;
    }
}

Пока что я могу выложить структуру с помощью поста, показанного здесь , а также в официальном doc .

Что я хочу:

Все, что я хочу сейчас, - это вызвать некоторые методы и начать читать строки / столбцы в ячейках файла Excel. Но я не могу понять, как? Что я могу сделать с помощью описанных выше методов, чтобы можно было извлечь значения ячеек из файлов Excel и сохранить их в, скажем, списках?

Все это было так просто при обычном подходе XSSF и HSSF, SAX сбивает меня с толку.

Что я пробовал

Пробовал читать все, что там есть в google и stackoverflow, но нигде не нашел пример, где они печатают реальные значения из ячеек Excel с использованием SAX-анализа.

Один из подходов в моей голове - реализовать итератор, который может получить несколько значений по порядку, но на самом деле не знаю, как.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...