2014-10-01 7 views
6

Ponieważ ByteArrayInputStream jest ograniczone do 2 GB, czy istnieje alternatywne rozwiązanie, które pozwala mi przechowywać całą zawartość pliku o wielkości 2,3 GB (i możliwie większego) w pliku InputStream, do odczytu przez Stax2?Czytanie pliku większego niż 2 GB w pamięci w Javie

Aktualny kod:

  XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); 
      XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(in); //ByteArrayInputStream???? 
      try 
      { 
       SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema"); 

       Schema schema = factory.newSchema(new StreamSource(schemaInputStream)); 
       Validator validator = schema.newValidator(); 
       validator.validate(new StAXSource(xmlStreamReader)); 

      } 

      finally 
      { 
       xmlStreamReader.close(); 
      } 

Dla tuningu, zmienna in nie musi pochodzić z dysku. Posiadam plenties pamięci RAM.

+0

W .NET ten sam problem istnieje i istnieje kilka rozwiązań. Spójrz na [to] (http://blogs.msdn.com/b/joshwil/archive/2005/08/10/450202.aspx) – ikh

+0

Możliwe jest dzielenie na kilka załączników (kilka plików)? –

Odpowiedz

1

Użyj NIO, aby przeczytać plik w gigantycznym ByteBuffer, a następnie utwórz klasę strumienia, która czyta ByteBuffer. Jest kilka takich pływających w otwartych źródłach.

0

Jeśli masz duże ilości pamięci, i tak nie osiągniesz żadnej poprawy wydajności. Odbieranie odbywa się tylko raz, a pamięć podręczna dysku zapewnia optymalne działanie. Wystarczy użyć strumienia wejściowego na dysku.

5

Cały punkt StAX2 polega na tym, że nie trzeba czytać pliku w pamięci. Możesz po prostu dostarczyć źródło i pozwolić StAX StreamReader na pobieranie danych zgodnie z potrzebami.

Jakie dodatkowe ograniczenia nie są wyświetlane w pytaniu?

Jeśli masz dużo pamięci, a chcesz uzyskać dobrą wydajność, tylko owinąć InputStream z dużym buforem bajtów, i niech bufor zrobić buforowania dla Ciebie:

// 4 meg buffer on the stream 
InputStream buffered = new BufferedInputStream(schemaInputStream, 1024 * 1024 * 4); 

Alternatywą do rozwiązania to w Javie ma utworzyć RAMDisk i przechowywać na nim plik, który usunie problem z Java, gdzie twoim podstawowym ograniczeniem jest to, że możesz mieć tylko mniej niż Integer.MAX_VALUE wartości w pojedynczej tablicy.

+2

Nie jestem testem wydajności, w którym muszę znaleźć wąskie gardło. Zostałem ** wyraźnie ** poproszony o wykonanie tego testu: załaduj cały plik do pamięci, zatwierdź go i dostarcz czas do mojego szefa. –

+0

Zmieniono moją odpowiedź, aby dodać koncepcję BufferedInputStream. Co do wymagań twojego szefa, nie ma możliwości utworzenia prostego segmentu pamięci o wartości większej niż 2Gig (bajty), więc musisz zrobić coś w rodzaju hackery (np. Wiele tablic bajtów lub przesuwanie bitowe lub okna pamięci lub coś takiego), aby tak się stało, co i tak wprowadza inne ograniczenia wydajności. Najlepiej jest utworzyć RAMDisk i załadować do niego plik, a następnie usunąć problem z Java. – rolfl

+1

Tak, miałem właśnie zasugerować dysk RAM. To się liczy? To wszystko w pamięci, oczywiście, choć nie wszystkie w pamięci JVM. –

-1

można wykorzystywać pamięć zapisu danych skompresowanych do

ByteArrayOutputStream baos = new ByteArrayOutputStream 
... new GZIPOutputStream(baos)); 

byte[] bytes = baos.toByteArray(); // < 100 MB? 

ByteArrayInputStream .... 

A potem zawinąć strumień wejściowy w GZIPInputStream.

Wciąż niewielkie spowolnienie, ale powinno być idealne dla XML.

+0

Dobre obejście dla przezwyciężenia zajętości pamięci. Zwłaszcza w przypadku XML plik o pojemności 2,3 GB jest deflowany do 70 MB. Powinienem przyjąć tę odpowiedź, ponieważ jest to doskonała odpowiedź, biorąc pod uwagę zakres pytania. Jednak pytanie nie jest dobrze sformułowane (problem X-Y): muszę wykonać test porównawczy sprawdzania poprawności XML, dla którego obciążenie kompresją nie jest najlepszym pomysłem. Tak więc twój nie może być ogólnym rozwiązaniem, ponieważ można mieć tak duże ilości danych, że po skompresowaniu przekracza 2 GB, ale to może prowadzić do innego świata pytań i odpowiedzi. –

+0

Dobrze, dziękuję za wciąż próbę (2,3 GB -> 70 MB) . Pozostawię odpowiedź dla innych z podobnymi pytaniami, ponieważ gzip jest często pomijany. Podobnie jak przy użyciu dysku RAM/SSD. –

+0

Właściwie, moja sprawa biznesowa (raportowanie ABS ABS) wymaga kompresji GZIP wytworzonego XML na dysku, więc nie musiałem wypróbowywać twojego kodu, już dostałem odpowiedź ;-) –