corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * CVS Identifier:
3 *
4 * $Id: BufferedRandomAccessFile.java,v 1.21 2001/04/15 14:34:29 grosbois Exp $
5 *
6 * Interface: RandomAccessIO.java
7 *
8 * Description: Abstract class for buffered random access I/O.
9 *
10 *
11 *
12 * COPYRIGHT:
13 *
14 * This software module was originally developed by Raphaël Grosbois and
15 * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
16 * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
17 * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
18 * Centre France S.A) in the course of development of the JPEG2000
19 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
20 * software module is an implementation of a part of the JPEG 2000
21 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
22 * Systems AB and Canon Research Centre France S.A (collectively JJ2000
23 * Partners) agree not to assert against ISO/IEC and users of the JPEG
24 * 2000 Standard (Users) any of their rights under the copyright, not
25 * including other intellectual property rights, for this software module
26 * with respect to the usage by ISO/IEC and Users of this software module
27 * or modifications thereof for use in hardware or software products
28 * claiming conformance to the JPEG 2000 Standard. Those intending to use
29 * this software module in hardware or software products are advised that
30 * their use may infringe existing patents. The original developers of
31 * this software module, JJ2000 Partners and ISO/IEC assume no liability
32 * for use of this software module or modifications thereof. No license
33 * or right to this software module is granted for non JPEG 2000 Standard
34 * conforming products. JJ2000 Partners have full right to use this
35 * software module for his/her own purpose, assign or donate this
36 * software module to any third party and to inhibit third parties from
37 * using this software module for non JPEG 2000 Standard conforming
38 * products. This copyright notice must be included in all copies or
39 * derivative works of this software module.
40 *
41 * Copyright (c) 1999/2000 JJ2000 Partners.
42 * */
43 using System;
44 namespace CSJ2K.j2k.io
45 {
46  
47 /// <summary> This class defines a Buffered Random Access File. It implements the
48 /// <tt>BinaryDataInput</tt> and <tt>BinaryDataOutput</tt> interfaces so that
49 /// binary data input/output can be performed. This class is abstract since no
50 /// assumption is done about the byte ordering type (little Endian, big
51 /// Endian). So subclasses will have to implement methods like
52 /// <tt>readShort()</tt>, <tt>writeShort()</tt>, <tt>readFloat()</tt>, ...
53 ///
54 /// <P><tt>BufferedRandomAccessFile</tt> (BRAF for short) is a
55 /// <tt>RandomAccessFile</tt> containing an extra buffer. When the BRAF is
56 /// accessed, it checks if the requested part of the file is in the buffer or
57 /// not. If that is the case, the read/write is done on the buffer. If not, the
58 /// file is uppdated to reflect the current status of the buffer and the file
59 /// is then accessed for a new buffer containing the requested byte/bit.
60 ///
61 /// </summary>
62 /// <seealso cref="RandomAccessIO">
63 /// </seealso>
64 /// <seealso cref="BinaryDataOutput">
65 /// </seealso>
66 /// <seealso cref="BinaryDataInput">
67 /// </seealso>
68 /// <seealso cref="BEBufferedRandomAccessFile">
69 ///
70 /// </seealso>
71 public abstract class BufferedRandomAccessFile : RandomAccessIO, EndianType
72 {
73 /// <summary> Returns the current offset in the file
74 ///
75 /// </summary>
76 virtual public int Pos
77 {
78 get
79 {
80 return (offset + position);
81 }
82  
83 }
84 /// <summary> Returns the endianess (i.e., byte ordering) of the implementing
85 /// class. Note that an implementing class may implement only one
86 /// type of endianness or both, which would be decided at creation
87 /// time.
88 ///
89 /// </summary>
90 /// <returns> Either <tt>EndianType.BIG_ENDIAN</tt> or
91 /// <tt>EndianType.LITTLE_ENDIAN</tt>
92 ///
93 /// </returns>
94 /// <seealso cref="EndianType">
95 ///
96 /// </seealso>
97 virtual public int ByteOrdering
98 {
99 get
100 {
101 return byte_Ordering;
102 }
103  
104 }
105  
106 /// <summary>The name of the current file </summary>
107 private System.String fileName;
108  
109 /// <summary> Whether the opened file is read only or not (defined by the constructor
110 /// arguments)
111 ///
112 /// </summary>
113 private bool isReadOnly = true;
114  
115 /// <summary> The RandomAccessFile associated with the buffer
116 ///
117 /// </summary>
118 //UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'"
119 private System.IO.FileStream theFile;
120  
121 /// <summary> Buffer of bytes containing the part of the file that is currently being
122 /// accessed
123 ///
124 /// </summary>
125 protected internal byte[] byteBuffer;
126  
127 /// <summary> Boolean keeping track of whether the byte buffer has been changed since
128 /// it was read.
129 ///
130 /// </summary>
131 protected internal bool byteBufferChanged;
132  
133 /// <summary> The current offset of the buffer (which will differ from the offset of
134 /// the file)
135 ///
136 /// </summary>
137 protected internal int offset;
138  
139 /// <summary> The current position in the byte-buffer
140 ///
141 /// </summary>
142 protected internal int position;
143  
144 /// <summary> The maximum number of bytes that can be read from the buffer
145 ///
146 /// </summary>
147 protected internal int maxByte;
148  
149 /// <summary> Whether the end of the file is in the current buffer or not
150 ///
151 /// </summary>
152 protected internal bool isEOFInBuffer;
153  
154 /* The endianess of the class */
155 protected internal int byte_Ordering;
156  
157 /// <summary> Constructor. Always needs a size for the buffer.
158 ///
159 /// </summary>
160 /// <param name="file">The file associated with the buffer
161 ///
162 /// </param>
163 /// <param name="mode">"r" for read, "rw" or "rw+" for read and write mode ("rw+"
164 /// opens the file for update whereas "rw" removes it
165 /// before. So the 2 modes are different only if the file
166 /// already exists).
167 ///
168 /// </param>
169 /// <param name="bufferSize">The number of bytes to buffer
170 ///
171 /// </param>
172 /// <exception cref="java.io.IOException">If an I/O error ocurred.
173 ///
174 /// </exception>
175 protected internal BufferedRandomAccessFile(System.IO.FileInfo file, System.String mode, int bufferSize)
176 {
177  
178 fileName = file.Name;
179 if (mode.Equals("rw") || mode.Equals("rw+"))
180 {
181 // mode read / write
182 isReadOnly = false;
183 if (mode.Equals("rw"))
184 {
185 // mode read / (over)write
186 bool tmpBool;
187 if (System.IO.File.Exists(file.FullName))
188 tmpBool = true;
189 else
190 tmpBool = System.IO.Directory.Exists(file.FullName);
191 if (tmpBool)
192 // Output file already exists
193 {
194 bool tmpBool2;
195 if (System.IO.File.Exists(file.FullName))
196 {
197 System.IO.File.Delete(file.FullName);
198 tmpBool2 = true;
199 }
200 else if (System.IO.Directory.Exists(file.FullName))
201 {
202 System.IO.Directory.Delete(file.FullName);
203 tmpBool2 = true;
204 }
205 else
206 tmpBool2 = false;
207 bool generatedAux = tmpBool2;
208 }
209 }
210 mode = "rw";
211 }
212 theFile = SupportClass.RandomAccessFileSupport.CreateRandomAccessFile(file, mode);
213 byteBuffer = new byte[bufferSize];
214 readNewBuffer(0);
215 }
216  
217 /// <summary> Constructor. Uses the default value for the byte-buffer
218 /// size (512 bytes).
219 ///
220 /// </summary>
221 /// <param name="file">The file associated with the buffer
222 ///
223 /// </param>
224 /// <param name="mode">"r" for read, "rw" or "rw+" for read and write mode
225 /// ("rw+" opens the file for update whereas "rw" removes
226 /// it before. So the 2 modes are different only if the
227 /// file already exists).
228 ///
229 /// </param>
230 /// <exception cref="java.io.IOException">If an I/O error ocurred.
231 ///
232 /// </exception>
233 protected internal BufferedRandomAccessFile(System.IO.FileInfo file, System.String mode):this(file, mode, 512)
234 {
235 }
236  
237 /// <summary> Constructor. Always needs a size for the buffer.
238 ///
239 /// </summary>
240 /// <param name="name">The name of the file associated with the buffer
241 ///
242 /// </param>
243 /// <param name="mode">"r" for read, "rw" or "rw+" for read and write mode
244 /// ("rw+" opens the file for update whereas "rw" removes
245 /// it before. So the 2 modes are different only if the
246 /// file already exists).
247 ///
248 /// </param>
249 /// <param name="bufferSize">The number of bytes to buffer
250 ///
251 /// </param>
252 /// <exception cref="java.io.IOException">If an I/O error ocurred.
253 ///
254 /// </exception>
255 protected internal BufferedRandomAccessFile(System.String name, System.String mode, int bufferSize):this(new System.IO.FileInfo(name), mode, bufferSize)
256 {
257 }
258  
259 /// <summary> Constructor. Uses the default value for the byte-buffer
260 /// size (512 bytes).
261 ///
262 /// </summary>
263 /// <param name="name">The name of the file associated with the buffer
264 ///
265 /// </param>
266 /// <param name="mode">"r" for read, "rw" or "rw+" for read and write mode
267 /// ("rw+" opens the file for update whereas "rw" removes
268 /// it before. So the 2 modes are different only if the
269 /// file already exists).
270 ///
271 /// </param>
272 /// <exception cref="java.io.IOException">If an I/O error ocurred.
273 ///
274 /// </exception>
275 protected internal BufferedRandomAccessFile(System.String name, System.String mode):this(name, mode, 512)
276 {
277 }
278  
279 /// <summary> Reads a new buffer from the file. If there has been any
280 /// changes made since the buffer was read, the buffer is
281 /// first written to the file.
282 ///
283 /// </summary>
284 /// <param name="off">The offset where to move to.
285 ///
286 /// </param>
287 /// <exception cref="java.io.IOException">If an I/O error ocurred.
288 ///
289 /// </exception>
290 protected internal void readNewBuffer(int off)
291 {
292  
293 /* If the buffer have changed. We need to write it to
294 * the file before reading a new buffer.
295 */
296 if (byteBufferChanged)
297 {
298 flush();
299 }
300 // Don't allow to seek beyond end of file if reading only
301 if (isReadOnly && off >= theFile.Length)
302 {
303 throw new System.IO.EndOfStreamException();
304 }
305 // Set new offset
306 offset = off;
307  
308 theFile.Seek(offset, System.IO.SeekOrigin.Begin);
309  
310 maxByte = theFile.Read(byteBuffer, 0, byteBuffer.Length);
311 position = 0;
312  
313 if (maxByte < byteBuffer.Length)
314 {
315 // Not enough data in input file.
316 isEOFInBuffer = true;
317 if (maxByte == - 1)
318 {
319 maxByte++;
320 }
321 }
322 else
323 {
324 isEOFInBuffer = false;
325 }
326 }
327  
328 /// <summary> Closes the buffered random access file
329 ///
330 /// </summary>
331 /// <exception cref="java.io.IOException">If an I/O error ocurred.
332 ///
333 /// </exception>
334 public virtual void close()
335 {
336 /* If the buffer has been changed, it need to be saved before
337 * closing
338 */
339 flush();
340 byteBuffer = null; // Release the byte-buffer reference
341 theFile.Close();
342 }
343  
344 /// <summary> Returns the current length of the stream, in bytes, taking into
345 /// account any buffering.
346 ///
347 /// </summary>
348 /// <returns> The length of the stream, in bytes.
349 ///
350 /// </returns>
351 /// <exception cref="java.io.IOException">If an I/O error ocurred.
352 ///
353 /// </exception>
354 public virtual int length()
355 {
356 int len;
357  
358 len = (int) theFile.Length;
359  
360 // If the position in the buffer is not past the end of the file,
361 // the length of theFile is the length of the stream
362 if ((offset + maxByte) <= len)
363 {
364 return (len);
365 }
366 else
367 {
368 // If not, the file is extended due to the buffering
369 return (offset + maxByte);
370 }
371 }
372  
373 /// <summary> Moves the current position to the given offset at which the
374 /// next read or write occurs. The offset is measured from the
375 /// beginning of the stream.
376 ///
377 /// </summary>
378 /// <param name="off">The offset where to move to.
379 ///
380 /// </param>
381 /// <exception cref="EOFException">If in read-only and seeking beyond EOF.
382 ///
383 /// </exception>
384 /// <exception cref="java.io.IOException">If an I/O error ocurred.
385 ///
386 /// </exception>
387 public virtual void seek(int off)
388 {
389 /* If the new offset is within the buffer, only the pos value needs
390 * to be modified. Else, the buffer must be moved. */
391 if ((off >= offset) && (off < (offset + byteBuffer.Length)))
392 {
393 if (isReadOnly && isEOFInBuffer && off > offset + maxByte)
394 {
395 // We are seeking beyond EOF in read-only mode!
396 throw new System.IO.EndOfStreamException();
397 }
398 position = off - offset;
399 }
400 else
401 {
402 readNewBuffer(off);
403 }
404 }
405  
406 /// <summary> Reads an unsigned byte of data from the stream. Prior to reading, the
407 /// stream is realigned at the byte level.
408 ///
409 /// </summary>
410 /// <returns> The byte read.
411 ///
412 /// </returns>
413 /// <exception cref="java.io.IOException">If an I/O error ocurred.
414 ///
415 /// </exception>
416 /// <exception cref="java.io.EOFException">If the end of file was reached
417 ///
418 /// </exception>
419 public byte readByte() { return read(); }
420 public byte readUnsignedByte() { return read(); }
421 public byte read()
422 {
423 if (position < maxByte)
424 {
425 // The byte can be read from the buffer
426 // In Java, the bytes are always signed.
427 return (byteBuffer[position++]);
428 }
429 else if (isEOFInBuffer)
430 {
431 // EOF is reached
432 position = maxByte + 1; // Set position to EOF
433 throw new System.IO.EndOfStreamException();
434 }
435 else
436 {
437 // End of the buffer is reached
438 readNewBuffer(offset + position);
439 return read();
440 }
441 }
442  
443 /// <summary> Reads up to len bytes of data from this file into an array of
444 /// bytes. This method reads repeatedly from the stream until all the bytes
445 /// are read. This method blocks until all the bytes are read, the end of
446 /// the stream is detected, or an exception is thrown.
447 ///
448 /// </summary>
449 /// <param name="b">The buffer into which the data is to be read. It must be long
450 /// enough.
451 ///
452 /// </param>
453 /// <param name="off">The index in 'b' where to place the first byte read.
454 ///
455 /// </param>
456 /// <param name="len">The number of bytes to read.
457 ///
458 /// </param>
459 /// <exception cref="EOFException">If the end-of file was reached before
460 /// getting all the necessary data.
461 ///
462 /// </exception>
463 /// <exception cref="IOException">If an I/O error ocurred.
464 ///
465 /// </exception>
466 public void readFully(byte[] b, int off, int len)
467 {
468 int clen; // current length to read
469 while (len > 0)
470 {
471 // There still is some data to read
472 if (position < maxByte)
473 {
474 // We can read some data from buffer
475 clen = maxByte - position;
476 if (clen > len)
477 clen = len;
478 Array.Copy(byteBuffer, position, b, off, clen);
479 position += clen;
480 off += clen;
481 len -= clen;
482 }
483 else if (isEOFInBuffer)
484 {
485 position = maxByte + 1; // Set position to EOF
486 throw new System.IO.EndOfStreamException();
487 }
488 else
489 {
490 // Buffer empty => get more data
491 readNewBuffer(offset + position);
492 }
493 }
494 }
495  
496 /// <summary> Writes a byte to the stream. Prior to writing, the stream is
497 /// realigned at the byte level.
498 ///
499 /// </summary>
500 /// <param name="b">The byte to write. The lower 8 bits of <tt>b</tt> are
501 /// written.
502 ///
503 /// </param>
504 /// <exception cref="java.io.IOException">If an I/O error ocurred.
505 ///
506 /// </exception>
507 public void write(int b)
508 {
509 // As long as pos is less than the length of the buffer we can write
510 // to the buffer. If the position is after the buffer a new buffer is
511 // needed
512 if (position < byteBuffer.Length)
513 {
514 if (isReadOnly)
515 throw new System.IO.IOException("File is read only");
516 byteBuffer[position] = (byte) b;
517 if (position >= maxByte)
518 {
519 maxByte = position + 1;
520 }
521 position++;
522 byteBufferChanged = true;
523 }
524 else
525 {
526 readNewBuffer(offset + position);
527 write(b);
528 }
529 }
530  
531 /// <summary> Writes a byte to the stream. Prior to writing, the stream is
532 /// realigned at the byte level.
533 ///
534 /// </summary>
535 /// <param name="b">The byte to write.
536 ///
537 /// </param>
538 /// <exception cref="java.io.IOException">If an I/O error ocurred.
539 ///
540 /// </exception>
541 public void write(byte b)
542 {
543 // As long as pos is less than the length of the buffer we can write
544 // to the buffer. If the position is after the buffer a new buffer is
545 // needed
546 if (position < byteBuffer.Length)
547 {
548 if (isReadOnly)
549 throw new System.IO.IOException("File is read only");
550 byteBuffer[position] = b;
551 if (position >= maxByte)
552 {
553 maxByte = position + 1;
554 }
555 position++;
556 byteBufferChanged = true;
557 }
558 else
559 {
560 readNewBuffer(offset + position);
561 write(b);
562 }
563 }
564  
565 /// <summary> Writes aan array of bytes to the stream. Prior to writing, the stream is
566 /// realigned at the byte level.
567 ///
568 /// </summary>
569 /// <param name="b">The array of bytes to write.
570 ///
571 /// </param>
572 /// <param name="offset">The first byte in b to write
573 ///
574 /// </param>
575 /// <param name="length">The number of bytes from b to write
576 ///
577 /// </param>
578 /// <exception cref="java.io.IOException">If an I/O error ocurred.
579 ///
580 /// </exception>
581 public void write(byte[] b, int offset, int length)
582 {
583 int i, stop;
584 stop = offset + length;
585 if (stop > b.Length)
586 throw new System. IndexOutOfRangeException("Index of bound " + b.Length);
587 for (i = offset; i < stop; i++)
588 {
589 write(b[i]);
590 }
591 }
592  
593 /// <summary> Writes the byte value of <tt>v</tt> (i.e., 8 least
594 /// significant bits) to the output. Prior to writing, the output
595 /// should be realigned at the byte level.
596 ///
597 /// <P>Signed or unsigned data can be written. To write a signed
598 /// value just pass the <tt>byte</tt> value as an argument. To
599 /// write unsigned data pass the <tt>int</tt> value as an argument
600 /// (it will be automatically casted, and only the 8 least
601 /// significant bits will be written).
602 ///
603 /// </summary>
604 /// <param name="v">The value to write to the output
605 ///
606 /// </param>
607 /// <exception cref="java.io.IOException">If an I/O error ocurred.
608 ///
609 /// </exception>
610 public void writeByte(int v)
611 {
612 write(v);
613 }
614  
615 /// <summary> Any data that has been buffered must be written (including
616 /// buffering at the bit level), and the stream should be realigned
617 /// at the byte level.
618 ///
619 /// </summary>
620 /// <exception cref="java.io.IOException">If an I/O error ocurred.
621 ///
622 /// </exception>
623 public void flush()
624 {
625 if (byteBufferChanged)
626 {
627 theFile.Seek(offset, System.IO.SeekOrigin.Begin);
628 theFile.Write(byteBuffer, 0, maxByte);
629 byteBufferChanged = false;
630 }
631 }
632 /*
633 /// <summary> Reads a signed byte (i.e., 8 bit) from the input. Prior to
634 /// reading, the input should be realigned at the byte level.
635 ///
636 /// </summary>
637 /// <returns> The next byte-aligned signed byte (8 bit) from the
638 /// input.
639 ///
640 /// </returns>
641 /// <exception cref="java.io.EOFException">If the end-of file was reached before
642 /// getting all the necessary data.
643 ///
644 /// </exception>
645 /// <exception cref="java.io.IOException">If an I/O error ocurred.
646 ///
647 /// </exception>
648 public byte readByte()
649 {
650 if (pos < maxByte)
651 {
652 // The byte can be read from the buffer
653 // In Java, the bytes are always signed.
654 return byteBuffer[pos++];
655 }
656 else if (isEOFInBuffer)
657 {
658 // EOF is reached
659 pos = maxByte + 1; // Set position to EOF
660 throw new System.IO.EndOfStreamException();
661 }
662 else
663 {
664 // End of the buffer is reached
665 readNewBuffer(offset + pos);
666 return readByte();
667 }
668 }
669  
670 /// <summary> Reads an unsigned byte (i.e., 8 bit) from the input. It is
671 /// returned as an <tt>int</tt> since Java does not have an
672 /// unsigned byte type. Prior to reading, the input should be
673 /// realigned at the byte level.
674 ///
675 /// </summary>
676 /// <returns> The next byte-aligned unsigned byte (8 bit) from the
677 /// input, as an <tt>int</tt>.
678 ///
679 /// </returns>
680 /// <exception cref="java.io.EOFException">If the end-of file was reached before
681 /// getting all the necessary data.
682 ///
683 /// </exception>
684 /// <exception cref="java.io.IOException">If an I/O error ocurred.
685 ///
686 /// </exception>
687 public int readUnsignedByte()
688 {
689 return read();
690 }
691 */
692 /// <summary> Skips <tt>n</tt> bytes from the input. Prior to skipping, the
693 /// input should be realigned at the byte level.
694 ///
695 /// </summary>
696 /// <param name="n">The number of bytes to skip
697 ///
698 /// </param>
699 /// <exception cref="java.io.EOFException">If the end-of file was reached before
700 /// all the bytes could be skipped.
701 ///
702 /// </exception>
703 /// <exception cref="java.io.IOException">If an I/O error ocurred.
704 ///
705 /// </exception>
706 public virtual int skipBytes(int n)
707 {
708 if (n < 0)
709 throw new System.ArgumentException("Can not skip negative number " + "of bytes");
710 if (n <= (maxByte - position))
711 {
712 position += n;
713 return n;
714 }
715 else
716 {
717 seek(offset + position + n);
718 return n;
719 }
720 }
721  
722 /// <summary> Returns a string of information about the file
723 ///
724 /// </summary>
725 public override System.String ToString()
726 {
727 return "BufferedRandomAccessFile: " + fileName + " (" + ((isReadOnly)?"read only":"read/write") + ")";
728 }
729 public abstract int readUnsignedShort();
730 public abstract void writeLong(long param1);
731 public abstract void writeShort(int param1);
732 public abstract float readFloat();
733 public abstract short readShort();
734 public abstract double readDouble();
735 public abstract int readInt();
736 public abstract long readLong();
737 public abstract long readUnsignedInt();
738 public abstract void writeDouble(double param1);
739 public abstract void writeFloat(float param1);
740 public abstract void writeInt(int param1);
741 }
742 }