# FileinputStream und BufferedInputStream



## bastel (28. Okt 2008)

Hi Freaks 

mal ne Frage: worin besteht eigetnlich der Unterschied zwischen 


```
byte [] data =new byter [(int)file.legnth)];
  FileInputStream inputstream = new FileInputStream(file);           
 inputstream.read(data);
```

und 


```
byte [] data =new byter [(int)file.legnth)];
 BufferedInputStream inputstream = new BufferedInputStream(new FileInputStream(file));           
 inputstream.read(data);
```


und wann sollte man was nehmen und vor allem: was ist perfomanter?

Ihr wisst das doch bestimmt  Danke!!


----------



## pinhead84 (28. Okt 2008)

```
byte [] data =new byter [(int)file.legnth)];
```
Das ist garnicht schön. Damit umgehst du das schöne Stream-Konzept von Java und reservierst eine Menge unnützen Speicher für dein Byte-Array.

Aber zu deiner Frage.

```
FileInputStream inputstream = new FileInputStream(file);
```
Dieser Stream operiert direkt auf der einzulesenden Datei. Übertrieben formuliert, wird mit jedem Aufruf von FileInputStream.read() auf der Festplatte die Datei durchsucht, bzw. ein Lesezugriff auf die Festplatte erfolgt.


```
BufferedInputStream inputstream = new BufferedInputStream(new FileInputStream(file));
```
In diesem Falle wird der Dateiinhalt in einem Buffer (ähnlich deinem Byte-Array) zwischengespeichert. Dadurch sollten weniger Leseoperationen auf der Festplatte nötig sein, was der Gesamtperformance zugute kommte. Dafür wird geringfügig mehr Speicher benötigt, um das Buffering zu realisieren.

Das Buffering ist keine allgemeine Anforderung des InputStream-Interfaces sondern wird über die BufferedInputStream-Klasse zur Verfügung gestellt und kann nach Bedarf verwendet werden.


----------



## Guest (29. Okt 2008)

Hallo nochmal , 

also ich brauche eine Methode, die mir aus einem File ein byte [] liefert. Das File ist sehr groß (700MB) und ich bekomme  hier immer ein heap space error. (Ich habe aktuell 512MB Speicher eingestellt) Hier mal der bisherige Code: 


```
public static byte [] mappedBuffer(String filename) throws Exception {
		FileInputStream f = new FileInputStream( filename );
		FileChannel ch = f.getChannel( );
		MappedByteBuffer mb = ch.map(MapMode.READ_ONLY,0L, ch.size( ) );
		byte[] barray = new byte[1024];
		long checkSum = 0L;
		int nGet;
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		while( mb.hasRemaining( ) )
		{
		    nGet = Math.min( mb.remaining( ), 1024 );
		    mb.get( barray, 0, nGet );
		    for ( int i=0; i<nGet; i++ ){
		        stream.write(barray[i]);
		        stream.flush();
		    }
		    
		    
		}
		stream.close();
		
		return stream.toByteArray();
		
	}
```

Gruß
bastel


----------



## pinhead84 (29. Okt 2008)

> also ich brauche eine Methode, die mir aus einem File ein byte [] liefert. Das File ist sehr groß (700MB) und ich bekomme hier immer ein heap space error. (Ich habe aktuell 512MB Speicher eingestellt)


Du wunderst dich, dass 512MB Speicher nicht genügen um eine 700MB-Datei in ein Byte-Array zu speichern?


----------



## Der Müde Joe (29. Okt 2008)

Wenn du 700MB in den Speicher lesen willst, benötigst du wohl auch 700MB Speicher.

EDIT:
zu langsam...
auf jeden Fall eine MENGE an Speicher


----------



## pinhead84 (29. Okt 2008)

Guten Morgen Joe 

Back 2 topic:
Wenn dein Programm 700MB an Speicher benötigt, solltest du ernsthaft über das Design nachdenken. Du kannst solch große Dateien in der Regel auch 'häppchenweise' verarbeiten und damit eine Menge Speicher sparen.


----------



## Der Müde Joe (29. Okt 2008)

pinhead84 hat gesagt.:
			
		

> Guten Morgen Joe



Guten Morgen   

mit dem FileChannel bist du eigentlich richtig (oder RandomAccessFile)
beide bieten die Möglichkeit die position in der man lesen will zu setzten
(position oder seek) und dann entsprechende bytes einlesen


----------



## Guest (29. Okt 2008)

ähm ja klingt eigentlich logisch  :roll: 

aber trotzdem, ich dachte mit dieser häppchenweise verarbeitung wäre obiges beispiel getan ?

Hier noch ein Beispiel von dem ich - für mein Verständnis- von einer häppchenweise Verarbeitung ausgehe oder liege ich da falsch ?

Nun habe ich 1024MB eingestellt, aber ich kriege trotzdem das heap space problem




```
public static byte[] readFile(String originalFilePath) throws IOException {
		
		FileInputStream fis = new FileInputStream(originalFilePath);
		byte[] buf = new byte[1024];
		int numRead = 0;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();

		while ((numRead = fis.read(buf)) > 0) {
			baos.write(buf, 0, numRead);
			baos.flush();
			
		}
		fis.close();
		byte[] returnVal = baos.toByteArray();
		baos.close();
		return returnVal;
	}
```


----------



## pinhead84 (29. Okt 2008)

> aber trotzdem, ich dachte mit dieser häppchenweise verarbeitung wäre obiges beispiel getan ?


So kann man es auch sehen. Häppchenweise schreibst du dein Byte-Array voll, bis es 'platzt'. 

Ich meinte damit etwas anderes. Wenn du z.B. eine große Textdatei zeilenweise verarbeiten willst, kann man dies mit dem LineNumberReader tun, OHNE vorher die gesamte Datei einlesen und zwischenspeichern zu müssen. Es wird dann immer nur die aktuelle Zeile im Speicher gehalten.

Was willst du mit dem Byte-Array denn anstellen, nachdem du es aus der Datei erzeugt hast?- Dann kann man dir auch sagen, wie du dein Problem ggf. eleganter und ohne solchen Speicherbedarf lösen kannst.


----------



## Guest (29. Okt 2008)

> So kann man es auch sehen. Häppchenweise schreibst du dein Byte-Array voll, bis es 'platzt'. icon_wink.gif



haha geil 

zum Anwendungsfall: ich benutze ein DMS (alfresco) und über einen WebService schreibe ich Daten in das DMS. 


```
webService.createContent(String root, String name, byte [] data, ...);
```

Dass große Dateien eingelesen werden müssen, da komme ich nicht drum rum. Es geht hier genauer um TIFF Dateien und ich benutze schon die JAI Api um diese zu handeln. Das mit den 700MB ist hoffentlich nicht realistisch und sollte nur ein Test sein, aber man muss davon ausgehen, dass bei der Übertragung schonmal 20-30 MB fällig sein können obwohl sich die TIFF Dateien mit der DEFLATE Kompression schon gut komprimieren lassen. (Die Dateien müssen original gespeichert werden, also kein jpg oder ähnliches). 


Nochmal zurück. Der folgende Code stammt von 

http://nadeausoftware.com/articles/...ad_files_quickly#FileInputStreamwithbytereads


```
public static byte [] mappedBuffer(String filename) throws Exception {
		FileInputStream f = new FileInputStream( filename );
		FileChannel ch = f.getChannel( );
		MappedByteBuffer mb = ch.map(MapMode.READ_ONLY,
		    0L, ch.size( ) );
		byte[] barray = new byte[1024];
		long checkSum = 0L;
		int nGet;
		while( mb.hasRemaining( ) )
		{
		    nGet = Math.min( mb.remaining( ), 1024 );
		    mb.get( barray, 0, nGet );
		    for ( int i=0; i<nGet; i++ )
		        checkSum += barray[i];
		}
		//dummy
		return new byte[0];		
	}

public static void main(String args[]) throws Exception {
	     long t = System.currentTimeMillis();
	      byte[] b = PerformanceTest.mappedBuffer("test.avi");
	      t = System.currentTimeMillis()-t; 

	}
```


----------



## Guest (29. Okt 2008)

hm irgendwie wurde der post automatisch ausgelöst...


meine Frage. kann mir jemand obigen Code erklären ? ich verstehe den nicht wirklich, überhaupt habe ich gestern das erste Mal was von dem nio package gehört ?
Wird in diesem Fall die test Datei (700MB) wirklich eingelesen ? 

Danke und Gruß von Sebastian!


----------



## pinhead84 (29. Okt 2008)

```
webService.createContent(String root, String name, byte [] data, ...);
```
Das ist wirklich dumm, aber anscheinend wirklich nicht zu ändern. So genau kenne ich Alfresco nicht. Frage doch im Zweifelsfalle mal direkt bei den Entwicklern nach, ob man nicht an dem Byte-Array vorbeikommt.

Sollte es kein Herumkommen um das Byte-Array geben, würde ich drüber nachdenken die Dateien zu komprimieren, auf kleinere Dateipakete aufzuteilen (z.B. 700MB = 70*10MB) und dann hochzuladen.

Unterstützt Alfresco nicht auch WebDAV? - Damit sollte du unkomplizierter streamen können, da WebDAV auf direkt auf HTTP aufsetzt.


----------



## Guest (29. Okt 2008)

> Unterstützt Alfresco nicht auch WebDAV? - Damit sollte du unkomplizierter streamen können, da WebDAV auf direkt auf HTTP aufsetzt.



soweit ich weiß ja, aber ich bin da noch am Anfang und das ist alles eine mühselige Angelegenheit. Ich werde mal probieren, die Daten aufzuteilen. Merci.


----------

