KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > nightlabs > io > DataBuffer


1 /* ************************************************************************** *
2  * Copyright (C) 2004 NightLabs GmbH, Marco Schulze *
3  * All rights reserved. *
4  * http://www.NightLabs.de *
5  * *
6  * This program and the accompanying materials are free software; you can re- *
7  * distribute it and/or modify it under the terms of the GNU General Public *
8  * License as published by the Free Software Foundation; either ver 2 of the *
9  * License, or any later version. *
10  * *
11  * This module is distributed in the hope that it will be useful, but WITHOUT *
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FIT- *
13  * NESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more *
14  * details. *
15  * *
16  * You should have received a copy of the GNU General Public License along *
17  * with this module; if not, write to the Free Software Foundation, Inc.: *
18  * 59 Temple Place, Suite 330 *
19  * Boston MA 02111-1307 *
20  * USA *
21  * *
22  * Or get it online: *
23  * http://www.opensource.org/licenses/gpl-license.php *
24  * *
25  * In case, you want to use this module or parts of it in a proprietary pro- *
26  * ject, you can purchase it under the NightLabs Commercial License. Please *
27  * contact NightLabs GmbH under info AT nightlabs DOT com for more infos or *
28  * visit http://www.NightLabs.com *
29  * ************************************************************************** */

30
31 package com.nightlabs.io;
32
33 import java.io.*;
34 import java.io.FileNotFoundException JavaDoc;
35 import java.io.IOException JavaDoc;
36
37 /**
38  * @author Marco Schulze
39  * @author Marc Klinger - marc at nightlabs dot de (API documentation fixes)
40  */

41 public class DataBuffer // implements IDataBuffer // , Cloneable
42
{
43   protected static int defaultMaxSizeForRAM = 4 * 1024 * 1024; // 4 MB
44
// protected static int defaultMaxSizeForRAM = 250;
45

46   protected static byte MODE_RAM = 0;
47   protected static byte MODE_FILE = 1;
48   protected byte mode = MODE_RAM;
49
50   public long expectedSize;
51   public int maxSizeForRAM;
52
53   protected byte[] data;
54
55   protected File file = null;
56 // protected FileOutputStream fout = null;
57
// protected FileInputStream fin = null;
58

59   protected long length = 0;
60
61
62 // protected int dataReadPos = 0;
63
// protected int dataMarkPos = 0;
64

65 // protected boolean isClosed = false;
66
// protected boolean osClosed = false;
67
// protected boolean readOnly = false;
68

69   private byte[] oneByteByteArray = new byte[1];
70
71 // public DataBuffer(int expectedSize, int maxSizeForRAM, String fileName)
72
// throws FileNotFoundException,
73
// IOException
74
// {
75
// this(expectedSize, maxSizeForRAM, fileName, false, false);
76
// }
77

78   public DataBuffer()
79     throws FileNotFoundException JavaDoc, IOException JavaDoc
80   {
81     this(1024);
82   }
83
84   public DataBuffer(long expectedSize, String JavaDoc _fileName)
85   throws FileNotFoundException JavaDoc,
86          IOException JavaDoc
87   {
88     this(expectedSize, defaultMaxSizeForRAM, new File(_fileName));
89   }
90
91   public DataBuffer(long expectedSize, File _file)
92   throws FileNotFoundException JavaDoc,
93          IOException JavaDoc
94   {
95     this(expectedSize, defaultMaxSizeForRAM, _file);
96   }
97
98   public DataBuffer(long expectedSize, int maxSizeForRAM, String JavaDoc _fileName)
99   throws FileNotFoundException JavaDoc,
100          IOException JavaDoc
101   {
102     this(expectedSize, maxSizeForRAM, new File(_fileName));
103   }
104
105   public DataBuffer(long expectedSize, int maxSizeForRAM, File _file)
106   throws FileNotFoundException JavaDoc,
107          IOException JavaDoc
108   {
109     this.expectedSize = expectedSize;
110     this.maxSizeForRAM = maxSizeForRAM;
111     this.file = _file;
112
113     if (expectedSize > maxSizeForRAM || (file != null && file.exists()))
114       this.mode = MODE_FILE;
115
116     if (this.mode == MODE_FILE) {
117       if (file == null)
118         file = File.createTempFile("DataBuffer", ".tmp");
119
120       length = file.length();
121     }
122     else {
123       data = new byte[(int)expectedSize];
124     }
125   }
126
127 // public DataBuffer(int expectedSize, int maxSizeForRAM)
128
// throws FileNotFoundException,
129
// IOException
130
// {
131
// this(expectedSize, maxSizeForRAM, null);
132
// }
133

134 // public DataBuffer(int expectedSize, String fileName)
135
// throws FileNotFoundException,
136
// IOException
137
// {
138
// this(expectedSize, defaultMaxSizeForRAM, fileName);
139
// }
140
//
141
// public DataBuffer(int expectedSize, String fileName, boolean append, boolean readOnly)
142
// throws FileNotFoundException,
143
// IOException
144
// {
145
// this(expectedSize, defaultMaxSizeForRAM, fileName, append, readOnly);
146
// }
147
//
148
public DataBuffer(long expectedSize)
149   throws FileNotFoundException JavaDoc,
150          IOException JavaDoc
151   {
152     this(expectedSize, defaultMaxSizeForRAM, (File)null);
153   }
154
155
156   protected FileInputStream createFileInputStream()
157   throws FileNotFoundException JavaDoc
158   {
159     if (mode != MODE_FILE)
160       throw new IllegalStateException JavaDoc("Cannot return a FileInputStream when not in MODE_FILE!");
161
162     return new FileInputStream(file);
163   }
164
165   /**
166    * This method creates a new InputStream to read from this DataBuffer. You
167    * can read at the same time on multiple threads from one DataBuffer.
168    * <p>
169    * Note, that the returned input stream is already buffered! You should not
170    * wrap a BufferedInputStream around!
171    *
172    * @return The new InputStream.
173    */

174   public InputStream createInputStream()
175   throws IOException JavaDoc
176   {
177     if (mode == MODE_FILE)
178       return new BufferedInputStream(new FileInputStream(file));
179     else
180       return new DataBufferInputStream(this);
181   }
182
183   /**
184     * This method creates a new OutputStream to write into this DataBuffer.
185     * You should be very careful when writing into one DataBuffer from multiple
186     * threads at the same time. Better don't do that! The result is
187     * unpredictable. At the moment, there is no multi-thread access supported.
188     * Thus, you should make sure, noone is reading while one thread writes!
189     * <p>
190     * Note, that the returned OutputStream is already buffered! You should not
191     * wrap a BufferedOutputStream around!
192     *
193     * @return The new OutputStream
194     */

195   public OutputStream createOutputStream()
196   throws IOException JavaDoc
197   {
198 // if (mode == MODE_FILE)
199
// return new FileOutputStream(file);
200
// else
201
return new DataBufferOutputStream(this);
202   }
203
204   protected void switchModeToFile()
205   throws IOException JavaDoc
206   {
207     if (mode == MODE_FILE)
208       return;
209
210     if (file == null)
211       file = File.createTempFile("DataBuffer", ".tmp");
212
213     os = new BufferedOutputStream(new FileOutputStream(file, false));
214
215     if (length > Integer.MAX_VALUE)
216       throw new IllegalStateException JavaDoc("length is too big! Switching mode to file should have happened earlier!");
217
218     os.write(data, 0, (int)length);
219     mode = MODE_FILE;
220     data = null; // damit der Müll schon weggeräumt werden kann ;-)
221
}
222
223   OutputStream os = null;
224   protected void closeOutputStream()
225   throws IOException JavaDoc
226   {
227     if (os != null) {
228       os.close();
229       os = null;
230     }
231   }
232
233   protected void flushOutputStream()
234   throws IOException JavaDoc
235   {
236     if (os != null)
237       os.flush();
238   }
239
240   protected void write(byte[] b, int off, int len)
241   throws IOException JavaDoc
242   {
243     if (mode == MODE_FILE) {
244       if (os == null)
245         os = new FileOutputStream(file, true);
246
247       os.write(b, off, len);
248     } // if (mode == MODE_FILE) {
249
else {
250
251       // Falls die maximale Größe für den RAM überschritten wird,
252
// alles in die Datei dumpen.
253

254       if (length + len > maxSizeForRAM) {
255         switchModeToFile();
256         os.write(b, off, len);
257       }
258       else {
259
260         if (data.length < length + len) {
261           byte[] tmpData = new byte[((int)length + len) * 8 / 6]; // vergroessern
262
System.arraycopy(data, 0, tmpData, 0, (int)length);
263           data = tmpData;
264         }
265
266         System.arraycopy(b, off, data, (int)length, len);
267       }
268     } // if (mode != MODE_FILE) {
269

270     length += len;
271   }
272
273 // public void write(byte[] b)
274
// throws IOException
275
// {
276
// write(b, 0, b.length);
277
// }
278
//
279
// public void write(int b)
280
// throws java.io.IOException
281
// {
282
// oneByteByteArray[0] = (byte)b;
283
// this.write(oneByteByteArray, 0, 1);
284
// }
285
//
286
// public int read()
287
// throws IOException
288
// {
289
// if (isClosed)
290
// throw new IOException("InputStream has already been closed!");
291
//
292
// if (fin != null)
293
// return fin.read();
294
// else {
295
// if (dataReadPos < length)
296
// return ((int)data[dataReadPos++]) & 0xff;
297
// else
298
// return -1;
299
// }
300
// }
301
//
302
// public int read(byte[] b, int off, int len)
303
// throws IOException
304
// {
305
// if (isClosed)
306
// throw new IOException("InputStream has already been closed!");
307
//
308
// int dr;
309
//
310
// if (fin != null)
311
// dr = fin.read(b, off, len);
312
// else {
313
// if (dataReadPos + len > length)
314
// len = length - dataReadPos;
315
//
316
// if (len > 0) {
317
// System.arraycopy(data, dataReadPos, b, off, len);
318
// dr = len;
319
// }
320
// else
321
// dr = -1;
322
// }
323
//
324
// if (dr > 0)
325
// dataReadPos += dr;
326
//
327
// return dr;
328
// }
329
//
330
// public int read(byte[] b)
331
// throws IOException
332
// {
333
// return read(b, 0, b.length);
334
// }
335
//
336
public long size()
337   {
338     return length;
339   }
340 //
341
// public int available()
342
// {
343
// int avl = length - dataReadPos;
344
//
345
// if (avl <= 0)
346
// avl = -1;
347
//
348
// return avl;
349
// }
350
//
351
// public void reset()
352
// throws IOException
353
// {
354
// if (fin != null)
355
// fin.reset();
356
//
357
// dataReadPos = dataMarkPos;
358
// }
359
//
360
//
361
// public long skip(long n)
362
// throws IOException
363
// {
364
// long bytesSkipped;
365
//
366
// if (fin != null)
367
// bytesSkipped = fin.skip(n);
368
// else {
369
// if (dataReadPos + n > length)
370
// bytesSkipped = length - dataReadPos;
371
// else
372
// bytesSkipped = n;
373
// }
374
//
375
// if (bytesSkipped > 0)
376
// dataReadPos += bytesSkipped;
377
//
378
// return bytesSkipped;
379
// }
380
//
381
// public void closeInputStream()
382
// throws IOException
383
// {
384
// if (fin != null) {
385
// fin.close();
386
// }
387
//
388
// isClosed = true;
389
// }
390
//
391
// public void flush()
392
// throws IOException
393
// {
394
// if (fout != null)
395
// fout.flush();
396
// }
397
//
398
// public boolean isOutputStreamClosed()
399
// {
400
// return osClosed;
401
// }
402
//
403
// public boolean isInputStreamClosed()
404
// {
405
// return isClosed;
406
// }
407
//
408
// public void closeOutputStream()
409
// throws IOException
410
// {
411
// if (fout != null) {
412
// fout.close();
413
// }
414
//
415
// osClosed = true;
416
// }
417
//
418
// public void seekToBeginning()
419
// throws IOException
420
// {
421
// if (dataReadPos==0)
422
// return;
423
//
424
// if (fin != null) {
425
// fin.close();
426
// fin = new FileInputStream(fileName);
427
// }
428
// dataReadPos = 0;
429
// }
430
//
431
//
432
/**
433      * This method copies the data within this databuffer into the destination
434      * file. If this databuffer represents a file, the file is copied, but
435      * the timestamp is not copied. This means, the new file's timestamp will
436      * always be the current system time.
437      *
438      * @param dest The file name (full path) of the destination file.
439      */

440     public void vomitFile(String JavaDoc dest)
441     throws IOException JavaDoc
442     {
443       vomitFile(new File(dest));
444     }
445
446     public void vomitFile(File dest)
447     throws IOException JavaDoc
448     {
449       this.closeOutputStream();
450
451       FileOutputStream o = new FileOutputStream(dest);
452
453       if (data != null) {
454         o.write(data);
455       }
456       else {
457         FileInputStream i = new FileInputStream(this.file);
458         byte[] b = new byte[8192];
459         int bytesRead;
460         while (true) {
461           bytesRead = i.read(b);
462           if (bytesRead <= 0)
463             break;
464
465           o.write(b, 0, bytesRead);
466         }
467
468       }
469
470       o.close();
471     }
472     
473     /**
474      * This generates a new byte array that has exactly the necessary length
475      * and contains all the data from this DataBuffer. Note, that this method
476      * may fail if this DataBuffer contains huge data.
477      *
478      * @return a byte array copy of this DataBuffer.
479      * @throws IOException
480      */

481     public byte[] createByteArray()
482         throws IOException JavaDoc
483     {
484         if (length > Integer.MAX_VALUE)
485             throw new ArrayIndexOutOfBoundsException JavaDoc("This DataBuffer contains too much data for a byte array!");
486
487         byte[] res = new byte[(int)length];
488
489         if (mode == MODE_RAM) {
490             System.arraycopy(data, 0, res, 0, res.length);
491         }
492         else if (mode == MODE_FILE) {
493             InputStream in = createInputStream();
494             try {
495                 int pos = 0;
496                 int bytesRead;
497                 do {
498                     bytesRead = in.read(res, pos, res.length - pos);
499                     if (bytesRead > 0)
500                         pos += bytesRead;
501                 } while (bytesRead >= 0 && pos < res.length);
502                 if (pos < res.length)
503                     throw new IOException JavaDoc("Could not read all bytes (stream broken): pos < res.length!");
504             } finally {
505                 in.close();
506             }
507         }
508         else
509             throw new IllegalStateException JavaDoc ("unknown mode: " + mode);
510
511         return res;
512     }
513
514 // public Object clone()
515
// {
516
// return clone(true);
517
// }
518
//
519
// public Object clone(boolean cloneBinary)
520
// {
521
// DataBuffer n = new DataBuffer(this.expectedSize);
522
// if (cloneBinary) {
523
// if (this.data != null) {
524
// n.data = (byte[])this.data.clone();
525
// }
526
// else {
527
// FileInputStream i = new FileInputStream(this.fileName);
528
// DataBufferOutputStream dbos = new DataBufferOutputStream(n);
529
// Utils.transferStreamData(i, dbos);
530
// dbos.close();
531
// } // else: if (this.data != null) {
532
// } // if (cloneBinary) {
533
// else {
534
// n.data = this.data;
535
// n.fileName = this.fileName;
536
// n.length = this.length;
537
// n.dataMarkPos = this.dataMarkPos;
538
// n.dataReadPos = this.dataReadPos;
539
// n.maxSizeForRAM = this.maxSizeForRAM;
540
// } // else: if (cloneBinary) {
541
//
542
// }
543

544 }
545
Popular Tags