Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook / 23 сообщений из 23, страница 1 из 1
18.12.2015, 14:45
    #39131896
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
Пробовал открыть xslx просто:
Код: java
1.
Workbook wb = WorkbookFactory.create(new File(FileName));


Вылетает по аутофмемори.
Посмотрел , народ пишет, надо использовать SXSSFWorkbook, но примера, как читать с пом. SXSSFWorkbook не нашел, в основном примеры записи большого xslx, с чтением непонятно.
...
Рейтинг: 0 / 0
18.12.2015, 15:09
    #39131932
chpasha
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
...
Рейтинг: 0 / 0
18.12.2015, 15:24
    #39131951
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
chpashaв гугле забанен?
Окак:
You can't. SXSSFWorkBook is write only, it doesn't support reading
For low memory reading of .xlsx files, you should look at the XSSF and SAX EventModel documentation


Капец, то есть нужно некий SAX ковырять?
...
Рейтинг: 0 / 0
18.12.2015, 15:29
    #39131958
chpasha
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
JDSchpashaв гугле забанен?
Окак:
You can't. SXSSFWorkBook is write only, it doesn't support reading
For low memory reading of .xlsx files, you should look at the XSSF and SAX EventModel documentation


Капец, то есть нужно некий SAX ковырять?
там в ответе и ссылка есть
...
Рейтинг: 0 / 0
18.12.2015, 15:32
    #39131963
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
chpashaтам в ответе и ссылка есть
Ага видел. Курю потихоньку. Спасиб )
...
Рейтинг: 0 / 0
18.12.2015, 16:06
    #39132016
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
Пробую тот пример:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
	public void processOneSheet(String filename) throws Exception {
                File f = new File(filename);
                if (f.exists()) 
                    System.out.println("yes");

		OPCPackage pkg = OPCPackage.open(filename);
		XSSFReader r = new XSSFReader(pkg);
		SharedStringsTable sst = r.getSharedStringsTable();

		XMLReader parser = fetchSheetParser(sst);

		// To look up the Sheet Name / Sheet Order / rID,
		//  you need to process the core Workbook stream.
		// Normally it's of the form rId# or rSheet#
		InputStream sheet2 = r.getSheet("rId2");
		InputSource sheetSource = new InputSource(sheet2);
		parser.parse(sheetSource);
		sheet2.close();
	}


Ломается на getSharedStringsTable:
автор Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/xmlbeans/XmlObject
at org.apache.poi.xssf.eventusermodel.XSSFReader.getSharedStringsTable(XSSFReader.java:82)


Плюс не пропускает XSSFRichTextString и getEntryAt в
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
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")) {
				System.out.println(lastContents);
			}
		}


Говорит, вроде как неправильный тип.
...
Рейтинг: 0 / 0
18.12.2015, 16:56
    #39132077
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
Почитал.
Подключил xmlbeans-2.3.0.jar, saxon9.jar, saxon9-dom.jar пошло дальше.
Теперь ломаемся на
Код: java
1.
XMLReader parser = fetchSheetParser(sst);


org.xml.sax.SAXException: SAX2 driver class org.apache.xerces.parsers.SAXParser not found
Почитал.
Подключил из xerces: xsercesiml.jar и xml-apis.jar
Вроде зашуршало.
Но это ж какая-то беда постоянно так кодить, копаясь в гугле, когда надо сваять что-то новое неужели все так живут? )
...
Рейтинг: 0 / 0
18.12.2015, 17:09
    #39132091
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
Теперь такая засада.
parser.parse(sheetSource);
Начинает читать файл сначала и до конца.
При этом адреса ячеек выводит типа A1, B1, C1 и т.д.
Можно ли как-то обращаться по конкретному адресу ячейки при чем по номерам ячеек типа (1,1) (2,1) и т.д.?
...
Рейтинг: 0 / 0
18.12.2015, 21:50
    #39132212
Garrick
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
JDSВылетает по аутофмемори.

А просто побольше памяти выделить не пробовали? -Xmx512m?
...
Рейтинг: 0 / 0
18.12.2015, 22:25
    #39132223
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
GarrickА просто побольше памяти выделить не пробовали? -Xmx512m?
Почему-то сразу отбросил этот вариант, т.к. при открытии этого файла ява-процесс отожрал больше гига каким-то чудом, хотя в файле всего около 100т записей (полей много правда), предположительно могут встречаться и файлы с бОльшим количеством.
Попробую увеличить, но если через SAX, выходит, что прежде надо будет например или закачать в память, но лучше наверно конвертировать хотя бы в обычный текстивик, а потом уже заливать (в базу надо закачать)?
...
Рейтинг: 0 / 0
21.12.2015, 11:10
    #39132847
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
Похоже, придется сначала перелить например в xls или ods, а потом уже работать, обращаясь по адресам ячеек :(
...
Рейтинг: 0 / 0
21.12.2015, 11:56
    #39132929
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
Ну да. Кто ж в xls засунет 100к записей. Есть еще вариант перелить все во временную табличку с двумя полями:
1. индексированное поле - адрес ячейки
2. значение
Может есть вариант создать индексированный файл? ) Можно самому намутить файл и индекс к нему или что-то навроде того, но тоже видится каким-то бредовым решением.
И вообще все это не вписывается в общую модель, т.е. хотелось бы иметь общий интерфейс для обращения ко всем типам файлов (опенофис и мсексель)...
...
Рейтинг: 0 / 0
21.12.2015, 12:57
    #39133022
chpasha
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
я правильно понял, ты забил на saxparser, потому что он тебе ячейки не в том формате выкидывает и теперь сидишь тут изобретаешь варианты один чудней другого?
...
Рейтинг: 0 / 0
21.12.2015, 14:04
    #39133113
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
chpashaя правильно понял, ты забил на saxparser
Не совсем забил, но почти.
То есть взял код из примера:
Код: java
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.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
package xlxtest;

import java.io.File;
import java.io.InputStream;

import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

public class Xlxtest {
	public void processOneSheet(String filename) throws Exception {
                File f = new File(filename);
                if (f.exists()) 
                    System.out.println("yes");

		OPCPackage pkg = OPCPackage.open(filename);
		XSSFReader r = new XSSFReader(pkg);
		SharedStringsTable sst = r.getSharedStringsTable();

		XMLReader parser = fetchSheetParser(sst);
                //String s = parser.getContentHandler().startElement();

		// To look up the Sheet Name / Sheet Order / rID,
		// you need to process the core Workbook stream.
		// Normally it's of the form rId# or rSheet#
		InputStream sheet2 = r.getSheet("rId1");
		InputSource sheetSource = new InputSource(sheet2);
		parser.parse(sheetSource);
		sheet2.close();
	}

	public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
		XMLReader parser =
			XMLReaderFactory.createXMLReader(
					"org.apache.xerces.parsers.SAXParser"
			);
		ContentHandler handler = new SheetHandler(sst);
		parser.setContentHandler(handler);
		return parser;
	}

	/** 
	 * See org.xml.sax.helpers.DefaultHandler javadocs 
	 */
	private static class SheetHandler extends DefaultHandler {
		private SharedStringsTable sst;
		private String lastContents;
		private boolean nextIsString;
		
		private SheetHandler(SharedStringsTable sst) {
			this.sst = sst;
		}
		
		public void startElement(String uri, String localName, String name,
				Attributes attributes) throws SAXException {
			// c => cell
			if(name.equals("c")) {
				// Print the cell reference
				System.out.print(attributes.getValue("r") + " - ");
				// Figure out if the value is an index in the SST
				String cellType = attributes.getValue("t");
				if(cellType != null && cellType.equals("s")) {
					nextIsString = true;
				} else {
					nextIsString = false;
				}
			}
			// 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")) {
				System.out.println(lastContents);
			}
		}

		public void characters(char[] ch, int start, int length)
				throws SAXException {
			lastContents += new String(ch, start, length);
		}
	}
	
	public static void main(String[] args) throws Exception {
		Xlxtest example = new Xlxtest();
		example.processOneSheet("d:\\test.xlsx");
	}
}


Который в startElement вроде как ловит адрес ячейки, в endElement содержимое ячейки, но в целом походу метод parse читает подряд весь файл и при этом не нашел возможности обращаться к ячейкам поадресно, а изучать весь этот SAX (если там вообще есть такая возможность) времени пока нет, может позже. Поэтому пока пишу вывод во временную табличку в БД, а уже с ней буду работать по ячейкам :(
...
Рейтинг: 0 / 0
21.12.2015, 15:43
    #39133286
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
Да. Заливать в базу файл в 100к записей пусть даже в 20 полей, разворачивая его "вертикально" по одной ячейке и получая на выходе 2млн записей - это бред конечно. Остается или как-то научиться адресоваться к ячейкам c помощью SAX или не трахать себе мозг, а поставить MSOffice и открывать файлы им, но на машине с линуксом тоже не вариант походу.
...
Рейтинг: 0 / 0
21.12.2015, 16:15
    #39133376
chpasha
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
я может чего проглядел, зачем нужно адресовать целенаправленно, если задача была прочитать и залить в базу? принцип работы saxparser-а всега один и тот же, он кидает тебе всю инфу, которая есть, ты выбираешь себе то что надо. Не прямая адресация "дай мне ячейку 1,2", а фильтрация - "если ячейка 1,2 -> то"
...
Рейтинг: 0 / 0
21.12.2015, 16:42
    #39133451
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
chpashaя может чего проглядел, зачем нужно адресовать целенаправленно, если задача была прочитать и залить в базу? принцип работы saxparser-а всега один и тот же, он кидает тебе всю инфу, которая есть, ты выбираешь себе то что надо. Не прямая адресация "дай мне ячейку 1,2", а фильтрация - "если ячейка 1,2 -> то"
Да. Это понял, если в этом паресере нет прямой адресации, то не очень.
Прежде чем заливать данные в БД, мне необходимо сопоставить поля (т.к. файлы не имеют единого формата), поэтому прежде перебираю листы файла (данные могут быть на любом листе), по контексту ищу нечто похожее на заголовок (необязательно он с первой строки и не обязательно занимает одну строку и т.д.), сопоставляю поля файла с полями в таблице БД (могут переставляться местами, добавляться новые) и дальше пошел читать все, что ниже заголовка, заливать в БД.

chpashaа фильтрация - "если ячейка 1,2 -> то
Да. Можно конечно и в этом варианте точно так же вычленить заголовок, сделать кроссировку и заливать дальше, просто помимо того, что нет единого формата файлы в принципе могут быть разными xls, ods, xlsx и для всех трех в принципе запилил общий интерфейс, только внутренняя реализация самого чтения отличалась, сейчас же из-за того, что не выходит адресоваться напрямую для xlsx эта универсальность немного рушится или ее надо переделывать, то есть типа убирать общий метод условно GetCell, а делать более глобальные методы классов типа LoadIntoDataBase. Т.е. до этого у меня была общая процедура разбора заголовков для всех типов файлов.
...
Рейтинг: 0 / 0
21.12.2015, 16:57
    #39133478
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
JDSДа. Это понял, если в этом паресере нет прямой адресации, то не очень.
А как ты себе такой парсер представляешь? Ты ему координаты, а он такой бац и по ним вычислил позицию в файле где читать значение? Это же не база данных.
...
Рейтинг: 0 / 0
21.12.2015, 17:05
    #39133495
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
Может есть аналог JRSwapFileVirtualizer как в Jasper?
...
Рейтинг: 0 / 0
21.12.2015, 17:10
    #39133513
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
BlazkowiczЭто же не база данных
Понимаю конечно, но надеялся на чудо )))
Всем спасибо, придется делать xlsx разбор "на лету"
...
Рейтинг: 0 / 0
29.12.2015, 11:45
    #39139902
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
Кстати как быть с датами? Они ж читаются просто как цифры.
Если посмотреть что пишут про формат хранения даты в екселе, то типа это кол-во дней, начиная с 01.01.1900.
В моем же случае опытным путем видно, что это кол-во дней, начиная с 30.12.1899.
Это что может меняться от файла к файлу ) Или от версии к версии офиса? )
Как быть в общем с датой? )
...
Рейтинг: 0 / 0
29.12.2015, 12:07
    #39139926
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
Вот еще нашел
Тип Date
При работе с этим типом данных следует иметь ввиду, что VBA-типы Date не являются такими же типами, как в рабочих листах Excel, хотя во многом и схожи с ними. Например, базовой датой для VBA-типа Date является 30 декабря 1899 года, а в Excel - 1 января 1900 года
И с огромной долей вероятности xlsx заполнен именно с помощью vba-макроса, а учитывая вышесказанное, вроде как и объясняется почему в ячеках числа с отсчетом с 1899-го. Но это ж трыднец какой-то :(
Вот пришел к тебе MSxlsx и как понять программно то ли с 1900, то ли 1899 циферки дат?? )
...
Рейтинг: 0 / 0
29.12.2015, 14:23
    #39140047
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook
Все-таки придется отталкиваться от даты 30.12.1899 + число ячейки в файле.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / POI и xlsx OutOfMemory открыть с пом. SXSSFWorkbook / 23 сообщений из 23, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]