| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738 |
- /*
- * Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
- *
- * Portions of this software were developed by the Unidata Program at the
- * University Corporation for Atmospheric Research.
- *
- * Access and use of this software shall impose the following obligations
- * and understandings on the user. The user is granted the right, without
- * any fee or cost, to use, copy, modify, alter, enhance and distribute
- * this software, and any derivative works thereof, and its supporting
- * documentation for any purpose whatsoever, provided that this entire
- * notice appears in all copies of the software, derivative works and
- * supporting documentation. Further, UCAR requests that the user credit
- * UCAR/Unidata in any publications that result from the use of this
- * software or in any product that includes this software. The names UCAR
- * and/or Unidata, however, may not be used in any advertising or publicity
- * to endorse or promote any products or commercial entity unless specific
- * written permission is obtained from UCAR/Unidata. The user also
- * understands that UCAR/Unidata is not obligated to provide the user with
- * any support, consulting, training or assistance of any kind with regard
- * to the use, operation and performance of this software nor to provide
- * the user with any updates, revisions, new versions or "bug fixes."
- *
- * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
- * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
- * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
- */
- package info.fetter.logstashforwarder.util;
- import java.io.*;
- import java.util.*;
- import java.util.concurrent.atomic.AtomicInteger;
- import java.util.concurrent.atomic.AtomicLong;
- import java.nio.channels.WritableByteChannel;
- /**
- * A buffered drop-in replacement for java.io.RandomAccessFile.
- * Instances of this class realise substantial speed increases over
- * java.io.RandomAccessFile through the use of buffering. This is a
- * subclass of Object, as it was not possible to subclass
- * java.io.RandomAccessFile because many of the methods are
- * final. However, if it is necessary to use RandomAccessFile and
- * java.io.RandomAccessFile interchangeably, both classes implement the
- * DataInput and DataOutput interfaces.
- * <p/>
- * <p> By Russ Rew, based on
- * BufferedRandomAccessFile by Alex McManus, based on Sun's source code
- * for java.io.RandomAccessFile. For Alex McManus version from which
- * this derives, see his <a href="http://www.aber.ac.uk/~agm/Java.html">
- * Freeware Java Classes</a>.
- * <p/>
- *
- * @author Alex McManus
- * @author Russ Rew
- * @author john caron
- * @see DataInput
- * @see DataOutput
- * @see java.io.RandomAccessFile
- */
- public class RandomAccessFile implements DataInput, DataOutput {
- static public final int BIG_ENDIAN = 0;
- static public final int LITTLE_ENDIAN = 1;
- // debug leaks - keep track of open files
- static protected boolean debugLeaks = false;
- static protected boolean debugAccess = false;
- static protected Set<String> allFiles = new HashSet<String>();
- static protected List<String> openFiles = Collections.synchronizedList(new ArrayList<String>());
- static private AtomicInteger debug_nseeks = new AtomicInteger();
- static private AtomicLong debug_nbytes = new AtomicLong();
- /**
- * Debugging, do not use.
- *
- * @return true if debugLeaks is on
- */
- static public boolean getDebugLeaks() {
- return debugLeaks;
- }
- /**
- * Debugging, do not use.
- *
- * @param b set true to track java.io.RandomAccessFile
- */
- static public void setDebugLeaks(boolean b) {
- debugLeaks = b;
- }
- /**
- * Debugging, do not use.
- *
- * @return list of open files.
- */
- static public List<String> getOpenFiles() {
- return openFiles;
- }
- static public List<String> getAllFiles() {
- List<String> result = new ArrayList<String>();
- if (null == allFiles) return null;
- Iterator<String> iter = allFiles.iterator();
- while (iter.hasNext()) {
- result.add( iter.next());
- }
- Collections.sort(result);
- return result;
- }
- /**
- * Debugging, do not use.
- *
- * @param b to debug file reading
- */
- static public void setDebugAccess(boolean b) {
- debugAccess = b;
- if (b) {
- debug_nseeks = new AtomicInteger();
- debug_nbytes = new AtomicLong();
- }
- }
- static public int getDebugNseeks() {
- return (debug_nseeks == null) ? 0 : debug_nseeks.intValue();
- }
- static public long getDebugNbytes() {
- return (debug_nbytes == null) ? 0 : debug_nbytes.longValue();
- }
- static protected boolean showOpen = false;
- static protected boolean showRead = false;
- /**
- * The default buffer size, in bytes.
- */
- protected static final int defaultBufferSize = 8092;
- /////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * File location
- */
- protected String location;
- /**
- * The underlying java.io.RandomAccessFile.
- */
- protected java.io.RandomAccessFile file;
- protected java.nio.channels.FileChannel fileChannel;
- /**
- * The offset in bytes from the file start, of the next read or
- * write operation.
- */
- protected long filePosition;
-
- /**
- * The buffer used for reading the data.
- */
- protected byte buffer[];
- /**
- * The offset in bytes of the start of the buffer, from the start of the file.
- */
- protected long bufferStart;
- /**
- * The offset in bytes of the end of the data in the buffer, from
- * the start of the file. This can be calculated from
- * <code>bufferStart + dataSize</code>, but it is cached to speed
- * up the read( ) method.
- */
- protected long dataEnd;
- /**
- * The size of the data stored in the buffer, in bytes. This may be
- * less than the size of the buffer.
- */
- protected int dataSize;
- /**
- * True if we are at the end of the file.
- */
- protected boolean endOfFile;
- /**
- * The access mode of the file.
- */
- protected boolean readonly;
- /**
- * The current endian (big or little) mode of the file.
- */
- protected boolean bigEndian;
- /**
- * True if the data in the buffer has been modified.
- */
- boolean bufferModified = false;
- /**
- * make sure file is this long when closed
- */
- private long minLength = 0;
- /**
- * stupid extendMode for truncated, yet valid files - old code allowed NOFILL to do this
- */
- boolean extendMode = false;
- /**
- * Constructor, for subclasses
- *
- * @param bufferSize size of read buffer
- */
- protected RandomAccessFile(int bufferSize) {
- file = null;
- readonly = true;
- init(bufferSize);
- }
- /**
- * Constructor, default buffer size.
- *
- * @param location location of the file
- * @param mode same as for java.io.RandomAccessFile
- * @throws IOException on open error
- */
- public RandomAccessFile(String location, String mode) throws IOException {
- this(location, mode, defaultBufferSize);
- this.location = location;
- }
- /**
- * Constructor.
- *
- * @param location location of the file
- * @param mode same as for java.io.RandomAccessFile
- * @param bufferSize size of buffer to use.
- * @throws IOException on open error
- */
- public RandomAccessFile(String location, String mode, int bufferSize) throws IOException {
- this.location = location;
- if (debugLeaks) {
- allFiles.add(location);
- if ((location.indexOf("01janN") >= 0) || (location.indexOf("02febN") >= 0))
- System.out.printf("HEY!%n");
- }
- this.file = new java.io.RandomAccessFile(location, mode);
- this.readonly = mode.equals("r");
- init(bufferSize);
- if (debugLeaks) {
- openFiles.add(location);
- if (showOpen) System.out.println(" open " + location);
- }
- }
- /**
- * Allow access to the underlying java.io.RandomAccessFile.
- * WARNING! BROKEN ENCAPSOLATION, DO NOT USE. May change implementation in the future.
- *
- * @return the underlying java.io.RandomAccessFile.
- */
- public java.io.RandomAccessFile getRandomAccessFile() {
- return this.file;
- }
- private void init(int bufferSize) {
- // Initialise the buffer
- bufferStart = 0;
- dataEnd = 0;
- dataSize = 0;
- filePosition = 0;
- buffer = new byte[bufferSize];
- endOfFile = false;
- }
- /**
- * Set the buffer size.
- * If writing, call flush() first.
- *
- * @param bufferSize length in bytes
- */
- public void setBufferSize(int bufferSize) {
- init(bufferSize);
- }
- /**
- * Get the buffer size
- *
- * @return bufferSize length in bytes
- */
- public int getBufferSize() {
- return buffer.length;
- }
- /**
- * Close the file, and release any associated system resources.
- *
- * @throws IOException if an I/O error occurrs.
- */
- public void close() throws IOException {
- if (debugLeaks) {
- openFiles.remove(location);
- if (showOpen) System.out.println(" close " + location);
- }
- if (file == null)
- return;
- // If we are writing and the buffer has been modified, flush the contents
- // of the buffer.
- flush();
- /*
- if (!readonly && bufferModified) {
- file.seek(bufferStart);
- file.write(buffer, 0, dataSize);
- } */
- // may need to extend file, in case no fill is being used
- // may need to truncate file in case overwriting a longer file
- // use only if minLength is set (by N3iosp)
- long fileSize = file.length();
- if (!readonly && (minLength != 0) && (minLength != fileSize)) {
- file.setLength(minLength);
- // System.out.println("TRUNCATE!!! minlength="+minLength);
- }
- // Close the underlying file object.
- file.close();
- //file = null; // help the gc => commented because of problems with nullpointerexceptions when trying to read after close
- }
- /**
- * Return true if file pointer is at end of file.
- *
- * @return true if file pointer is at end of file
- */
- public boolean isAtEndOfFile() {
- return endOfFile;
- }
- /**
- * Set the position in the file for the next read or write.
- *
- * @param pos the offset (in bytes) from the start of the file.
- * @throws IOException if an I/O error occurrs.
- */
- public void seek(long pos) throws IOException {
- // If the seek is into the buffer, just update the file pointer.
- if ((pos >= bufferStart) && (pos < dataEnd)) {
- filePosition = pos;
- return;
- }
- // need new buffer, starting at pos
- readBuffer(pos);
- }
- protected void readBuffer(long pos) throws IOException {
- // If the current buffer is modified, write it to disk.
- if (bufferModified) {
- flush();
- }
- bufferStart = pos;
- filePosition = pos;
- dataSize = read_(pos, buffer, 0, buffer.length);
- if (dataSize <= 0) {
- dataSize = 0;
- endOfFile = true;
- } else {
- endOfFile = false;
- }
- // Cache the position of the buffer end.
- dataEnd = bufferStart + dataSize;
- }
- /**
- * Returns the current position in the file, where the next read or
- * write will occur.
- *
- * @return the offset from the start of the file in bytes.
- * @throws IOException if an I/O error occurrs.
- */
- public long getFilePointer() throws IOException {
- return filePosition;
- }
- /**
- * Get the file location, or name.
- *
- * @return file location
- */
- public String getLocation() {
- return location;
- }
- /**
- * Get the length of the file. The data in the buffer (which may not
- * have been written the disk yet) is taken into account.
- *
- * @return the length of the file in bytes.
- * @throws IOException if an I/O error occurrs.
- */
- public long length() throws IOException {
- long fileLength = file.length();
- if (fileLength < dataEnd) {
- return dataEnd;
- } else {
- return fileLength;
- }
- }
- /**
- * Change the current endian mode. Subsequent reads of short, int, float, double, long, char will
- * use this. Does not currently affect writes.
- * Default values is BIG_ENDIAN.
- *
- * @param endian RandomAccessFile.BIG_ENDIAN or RandomAccessFile.LITTLE_ENDIAN
- */
- public void order(int endian) {
- if (endian < 0) return;
- this.bigEndian = (endian == BIG_ENDIAN);
- }
- /**
- * Returns the opaque file descriptor object associated with this file.
- *
- * @return the file descriptor object associated with this file.
- * @throws IOException if an I/O error occurs.
- */
- public FileDescriptor getFD() throws IOException {
- return (file == null) ? null : file.getFD();
- }
- /**
- * Copy the contents of the buffer to the disk.
- *
- * @throws IOException if an I/O error occurs.
- */
- public void flush() throws IOException {
- if (bufferModified) {
- file.seek(bufferStart);
- file.write(buffer, 0, dataSize);
- //System.out.println("--flush at "+bufferStart+" dataSize= "+dataSize+ " filePosition= "+filePosition);
- bufferModified = false;
- }
- /* check min length
- if (!readonly && (minLength != 0) && (minLength != file.length())) {
- file.setLength(minLength);
- } */
- }
- /**
- * Make sure file is at least this long when its closed.
- * needed when not using fill mode, and not all data is written.
- *
- * @param minLength minimum length of the file.
- */
- public void setMinLength(long minLength) {
- this.minLength = minLength;
- }
- /**
- * Set extendMode for truncated, yet valid files - old NetCDF code allowed this
- * when NOFILL on, and user doesnt write all variables.
- */
- public void setExtendMode() {
- this.extendMode = true;
- }
- //////////////////////////////////////////////////////////////////////////////////////////////
- // Read primitives.
- //
- /**
- * Read a byte of data from the file, blocking until data is
- * available.
- *
- * @return the next byte of data, or -1 if the end of the file is
- * reached.
- * @throws IOException if an I/O error occurrs.
- */
- public int read() throws IOException {
- // If the file position is within the data, return the byte...
- if (filePosition < dataEnd) {
- int pos = (int) (filePosition - bufferStart);
- filePosition++;
- return (buffer[pos] & 0xff);
- // ...or should we indicate EOF...
- } else if (endOfFile) {
- return -1;
- // ...or seek to fill the buffer, and try again.
- } else {
- seek(filePosition);
- return read();
- }
- }
- /**
- * Read up to <code>len</code> bytes into an array, at a specified
- * offset. This will block until at least one byte has been read.
- *
- * @param b the byte array to receive the bytes.
- * @param off the offset in the array where copying will start.
- * @param len the number of bytes to copy.
- * @return the actual number of bytes read, or -1 if there is not
- * more data due to the end of the file being reached.
- * @throws IOException if an I/O error occurrs.
- */
- protected int readBytes(byte b[], int off, int len) throws IOException {
- // Check for end of file.
- if (endOfFile) {
- return -1;
- }
- // See how many bytes are available in the buffer - if none,
- // seek to the file position to update the buffer and try again.
- int bytesAvailable = (int) (dataEnd - filePosition);
- if (bytesAvailable < 1) {
- seek(filePosition);
- return readBytes(b, off, len);
- }
- // Copy as much as we can.
- int copyLength = (bytesAvailable >= len)
- ? len
- : bytesAvailable;
- System.arraycopy(buffer, (int) (filePosition - bufferStart), b, off, copyLength);
- filePosition += copyLength;
- // If there is more to copy...
- if (copyLength < len) {
- int extraCopy = len - copyLength;
- // If the amount remaining is more than a buffer's length, read it
- // directly from the file.
- if (extraCopy > buffer.length) {
- extraCopy = read_(filePosition, b, off + copyLength, len - copyLength);
- // ...or read a new buffer full, and copy as much as possible...
- } else {
- seek(filePosition);
- if (!endOfFile) {
- extraCopy = (extraCopy > dataSize)
- ? dataSize
- : extraCopy;
- System.arraycopy(buffer, 0, b, off + copyLength, extraCopy);
- } else {
- extraCopy = -1;
- }
- }
- // If we did manage to copy any more, update the file position and
- // return the amount copied.
- if (extraCopy > 0) {
- filePosition += extraCopy;
- return copyLength + extraCopy;
- }
- }
- // Return the amount copied.
- return copyLength;
- }
- /**
- * Read <code>nbytes</code> bytes, at the specified file offset, send to a WritableByteChannel.
- * This will block until all bytes are read.
- * This uses the underlying file channel directly, bypassing all user buffers.
- *
- * @param dest write to this WritableByteChannel.
- * @param offset the offset in the file where copying will start.
- * @param nbytes the number of bytes to read.
- * @return the actual number of bytes read and transfered
- * @throws IOException if an I/O error occurs.
- */
- public long readToByteChannel(WritableByteChannel dest, long offset, long nbytes) throws IOException {
- if (fileChannel == null)
- fileChannel = file.getChannel();
- long need = nbytes;
- while (need > 0) {
- long count = fileChannel.transferTo(offset, need, dest);
- //if (count == 0) break; // LOOK not sure what the EOF condition is
- need -= count;
- offset += count;
- }
- return nbytes - need;
- }
- /**
- * Read directly from file, without going through the buffer.
- * All reading goes through here or readToByteChannel;
- *
- * @param pos start here in the file
- * @param b put data into this buffer
- * @param offset buffer offset
- * @param len this number of bytes
- * @return actual number of bytes read
- * @throws IOException on io error
- */
- protected int read_(long pos, byte[] b, int offset, int len) throws IOException {
- file.seek(pos);
- int n = file.read(b, offset, len);
- if (debugAccess) {
- if (showRead) System.out.println(" **read_ " + location + " = " + len + " bytes at " + pos + "; block = " + (pos / buffer.length));
- debug_nseeks.incrementAndGet();
- debug_nbytes.addAndGet(len);
- }
- if (extendMode && (n < len)) {
- //System.out.println(" read_ = "+len+" at "+pos+"; got = "+n);
- n = len;
- }
- return n;
- }
- /**
- * Read up to <code>len</code> bytes into an array, at a specified
- * offset. This will block until at least one byte has been read.
- *
- * @param b the byte array to receive the bytes.
- * @param off the offset in the array where copying will start.
- * @param len the number of bytes to copy.
- * @return the actual number of bytes read, or -1 if there is not
- * more data due to the end of the file being reached.
- * @throws IOException if an I/O error occurrs.
- */
- public int read(byte b[], int off, int len) throws IOException {
- return readBytes(b, off, len);
- }
- /**
- * Read up to <code>b.length( )</code> bytes into an array. This
- * will block until at least one byte has been read.
- *
- * @param b the byte array to receive the bytes.
- * @return the actual number of bytes read, or -1 if there is not
- * more data due to the end of the file being reached.
- * @throws IOException if an I/O error occurrs.
- */
- public int read(byte b[]) throws IOException {
- return readBytes(b, 0, b.length);
- }
- /**
- * Read fully count number of bytes
- *
- * @param count how many bytes tp read
- * @return a byte array of length count, fully read in
- * @throws IOException if an I/O error occurrs.
- */
- public byte[] readBytes(int count) throws IOException {
- byte[] b = new byte[count];
- readFully(b);
- return b;
- }
- /**
- * Reads <code>b.length</code> bytes from this file into the byte
- * array. This method reads repeatedly from the file until all the
- * bytes are read. This method blocks until all the bytes are read,
- * the end of the stream is detected, or an exception is thrown.
- *
- * @param b the buffer into which the data is read.
- * @throws EOFException if this file reaches the end before reading
- * all the bytes.
- * @throws IOException if an I/O error occurs.
- */
- public final void readFully(byte b[]) throws IOException {
- readFully(b, 0, b.length);
- }
- /**
- * Reads exactly <code>len</code> bytes from this file into the byte
- * array. This method reads repeatedly from the file until all the
- * bytes are read. This method blocks until all the bytes are read,
- * the end of the stream is detected, or an exception is thrown.
- *
- * @param b the buffer into which the data is read.
- * @param off the start offset of the data.
- * @param len the number of bytes to read.
- * @throws EOFException if this file reaches the end before reading
- * all the bytes.
- * @throws IOException if an I/O error occurs.
- */
- public final void readFully(byte b[], int off, int len) throws IOException {
- int n = 0;
- while (n < len) {
- int count = this.read(b, off + n, len - n);
- if (count < 0) {
- throw new EOFException();
- }
- n += count;
- }
- }
- /**
- * Skips exactly <code>n</code> bytes of input.
- * This method blocks until all the bytes are skipped, the end of
- * the stream is detected, or an exception is thrown.
- *
- * @param n the number of bytes to be skipped.
- * @return the number of bytes skipped, which is always <code>n</code>.
- * @throws EOFException if this file reaches the end before skipping
- * all the bytes.
- * @throws IOException if an I/O error occurs.
- */
- public int skipBytes(int n) throws IOException {
- seek(getFilePointer() + n);
- return n;
- }
- /* public void skipToMultiple( int multipleOfBytes) throws IOException {
- long pos = getFilePointer();
- int pad = (int) (pos % multipleOfBytes);
- if (pad != 0) pad = multipleOfBytes - pad;
- if (pad > 0) skipBytes(pad);
- } */
- /**
- * Unread the last byte read.
- * This method should not be used more than once
- * between reading operations, or strange things might happen.
- */
- public void unread() {
- filePosition--;
- }
- //
- // Write primitives.
- //
- /**
- * Write a byte to the file. If the file has not been opened for
- * writing, an IOException will be raised only when an attempt is
- * made to write the buffer to the file.
- * <p/>
- * Caveat: the effects of seek( )ing beyond the end of the file are
- * undefined.
- *
- * @param b write this byte
- * @throws IOException if an I/O error occurrs.
- */
- public void write(int b) throws IOException {
- // If the file position is within the block of data...
- if (filePosition < dataEnd) {
- int pos = (int) (filePosition - bufferStart);
- buffer[pos] = (byte) b;
- bufferModified = true;
- filePosition++;
- // ...or (assuming that seek will not allow the file pointer
- // to move beyond the end of the file) get the correct block of
- // data...
- } else {
- // If there is room in the buffer, expand it...
- if (dataSize != buffer.length) {
- int pos = (int) (filePosition - bufferStart);
- buffer[pos] = (byte) b;
- bufferModified = true;
- filePosition++;
- dataSize++;
- dataEnd++;
- // ...or do another seek to get a new buffer, and start again...
- } else {
- seek(filePosition);
- write(b);
- }
- }
- }
- /**
- * Write <code>len</code> bytes from an array to the file.
- *
- * @param b the array containing the data.
- * @param off the offset in the array to the data.
- * @param len the length of the data.
- * @throws IOException if an I/O error occurrs.
- */
- public void writeBytes(byte b[], int off, int len) throws IOException {
- // If the amount of data is small (less than a full buffer)...
- if (len < buffer.length) {
- // If any of the data fits within the buffer...
- int spaceInBuffer = 0;
- int copyLength = 0;
- if (filePosition >= bufferStart) {
- spaceInBuffer = (int) ((bufferStart + buffer.length) - filePosition);
- }
- if (spaceInBuffer > 0) {
- // Copy as much as possible to the buffer.
- copyLength = (spaceInBuffer > len) ? len : spaceInBuffer;
- System.arraycopy(b, off, buffer, (int) (filePosition - bufferStart), copyLength);
- bufferModified = true;
- long myDataEnd = filePosition + copyLength;
- dataEnd = (myDataEnd > dataEnd) ? myDataEnd : dataEnd;
- dataSize = (int) (dataEnd - bufferStart);
- filePosition += copyLength;
- ///System.out.println("--copy to buffer "+copyLength+" "+len);
- }
- // If there is any data remaining, move to the new position and copy to
- // the new buffer.
- if (copyLength < len) {
- //System.out.println("--need more "+copyLength+" "+len+" space= "+spaceInBuffer);
- seek(filePosition); // triggers a flush
- System.arraycopy(b, off + copyLength, buffer, (int) (filePosition - bufferStart), len - copyLength);
- bufferModified = true;
- long myDataEnd = filePosition + (len - copyLength);
- dataEnd = (myDataEnd > dataEnd) ? myDataEnd : dataEnd;
- dataSize = (int) (dataEnd - bufferStart);
- filePosition += (len - copyLength);
- }
- // ...or write a lot of data...
- } else {
- // Flush the current buffer, and write this data to the file.
- if (bufferModified) {
- flush();
- }
- file.seek(filePosition); // moved per Steve Cerruti; Jan 14, 2005
- file.write(b, off, len);
- //System.out.println("--write at "+filePosition+" "+len);
- filePosition += len;
- bufferStart = filePosition; // an empty buffer
- dataSize = 0;
- dataEnd = bufferStart + dataSize;
- }
- }
- /**
- * Writes <code>b.length</code> bytes from the specified byte array
- * starting at offset <code>off</code> to this file.
- *
- * @param b the data.
- * @throws IOException if an I/O error occurs.
- */
- public void write(byte b[]) throws IOException {
- writeBytes(b, 0, b.length);
- }
- /**
- * Writes <code>len</code> bytes from the specified byte array
- * starting at offset <code>off</code> to this file.
- *
- * @param b the data.
- * @param off the start offset in the data.
- * @param len the number of bytes to write.
- * @throws IOException if an I/O error occurs.
- */
- public void write(byte b[], int off, int len) throws IOException {
- writeBytes(b, off, len);
- }
- //
- // DataInput methods.
- //
- /**
- * Reads a <code>boolean</code> from this file. This method reads a
- * single byte from the file. A value of <code>0</code> represents
- * <code>false</code>. Any other value represents <code>true</code>.
- * This method blocks until the byte is read, the end of the stream
- * is detected, or an exception is thrown.
- *
- * @return the <code>boolean</code> value read.
- * @throws EOFException if this file has reached the end.
- * @throws IOException if an I/O error occurs.
- */
- public final boolean readBoolean() throws IOException {
- int ch = this.read();
- if (ch < 0) {
- throw new EOFException();
- }
- return (ch != 0);
- }
- /**
- * Reads a signed 8-bit value from this file. This method reads a
- * byte from the file. If the byte read is <code>b</code>, where
- * <code>0 <= b <= 255</code>,
- * then the result is:
- * <ul><code>
- * (byte)(b)
- * </code></ul>
- * <p/>
- * This method blocks until the byte is read, the end of the stream
- * is detected, or an exception is thrown.
- *
- * @return the next byte of this file as a signed 8-bit
- * <code>byte</code>.
- * @throws EOFException if this file has reached the end.
- * @throws IOException if an I/O error occurs.
- */
- public final byte readByte() throws IOException {
- int ch = this.read();
- if (ch < 0) {
- throw new EOFException();
- }
- return (byte) (ch);
- }
- /**
- * Reads an unsigned 8-bit number from this file. This method reads
- * a byte from this file and returns that byte.
- * <p/>
- * This method blocks until the byte is read, the end of the stream
- * is detected, or an exception is thrown.
- *
- * @return the next byte of this file, interpreted as an unsigned
- * 8-bit number.
- * @throws EOFException if this file has reached the end.
- * @throws IOException if an I/O error occurs.
- */
- public final int readUnsignedByte() throws IOException {
- int ch = this.read();
- if (ch < 0) {
- throw new EOFException();
- }
- return ch;
- }
- /**
- * Reads a signed 16-bit number from this file. The method reads 2
- * bytes from this file. If the two bytes read, in order, are
- * <code>b1</code> and <code>b2</code>, where each of the two values is
- * between <code>0</code> and <code>255</code>, inclusive, then the
- * result is equal to:
- * <ul><code>
- * (short)((b1 << 8) | b2)
- * </code></ul>
- * <p/>
- * This method blocks until the two bytes are read, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return the next two bytes of this file, interpreted as a signed
- * 16-bit number.
- * @throws EOFException if this file reaches the end before reading
- * two bytes.
- * @throws IOException if an I/O error occurs.
- */
- public final short readShort() throws IOException {
- int ch1 = this.read();
- int ch2 = this.read();
- if ((ch1 | ch2) < 0) {
- throw new EOFException();
- }
- if (bigEndian) {
- return (short) ((ch1 << 8) + (ch2));
- } else {
- return (short) ((ch2 << 8) + (ch1));
- }
- }
- /**
- * Read an array of shorts
- *
- * @param pa read into this array
- * @param start starting at pa[start]
- * @param n read this many elements
- * @throws IOException on read error
- */
- public final void readShort(short[] pa, int start, int n) throws IOException {
- for (int i = 0; i < n; i++) {
- pa[start + i] = readShort();
- }
- }
- /**
- * Reads an unsigned 16-bit number from this file. This method reads
- * two bytes from the file. If the bytes read, in order, are
- * <code>b1</code> and <code>b2</code>, where
- * <code>0 <= b1, b2 <= 255</code>,
- * then the result is equal to:
- * <ul><code>
- * (b1 << 8) | b2
- * </code></ul>
- * <p/>
- * This method blocks until the two bytes are read, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return the next two bytes of this file, interpreted as an unsigned
- * 16-bit integer.
- * @throws EOFException if this file reaches the end before reading
- * two bytes.
- * @throws IOException if an I/O error occurs.
- */
- public final int readUnsignedShort() throws IOException {
- int ch1 = this.read();
- int ch2 = this.read();
- if ((ch1 | ch2) < 0) {
- throw new EOFException();
- }
- if (bigEndian) {
- return ((ch1 << 8) + (ch2));
- } else {
- return ((ch2 << 8) + (ch1));
- }
- }
- /*
- * Reads a signed 24-bit integer from this file. This method reads 3
- * bytes from the file. If the bytes read, in order, are <code>b1</code>,
- * <code>b2</code>, and <code>b3</code>, where
- * <code>0 <= b1, b2, b3 <= 255</code>,
- * then the result is equal to:
- * <ul><code>
- * (b1 << 16) | (b2 << 8) + (b3 << 0)
- * </code></ul>
- * <p/>
- * This method blocks until the three bytes are read, the end of the
- * stream is detected, or an exception is thrown.
- */
- /**
- * Reads a Unicode character from this file. This method reads two
- * bytes from the file. If the bytes read, in order, are
- * <code>b1</code> and <code>b2</code>, where
- * <code>0 <= b1, b2 <= 255</code>,
- * then the result is equal to:
- * <ul><code>
- * (char)((b1 << 8) | b2)
- * </code></ul>
- * <p/>
- * This method blocks until the two bytes are read, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return the next two bytes of this file as a Unicode character.
- * @throws EOFException if this file reaches the end before reading
- * two bytes.
- * @throws IOException if an I/O error occurs.
- */
- public final char readChar() throws IOException {
- int ch1 = this.read();
- int ch2 = this.read();
- if ((ch1 | ch2) < 0) {
- throw new EOFException();
- }
- if (bigEndian) {
- return (char) ((ch1 << 8) + (ch2));
- } else {
- return (char) ((ch2 << 8) + (ch1));
- }
- }
- /**
- * Reads a signed 32-bit integer from this file. This method reads 4
- * bytes from the file. If the bytes read, in order, are <code>b1</code>,
- * <code>b2</code>, <code>b3</code>, and <code>b4</code>, where
- * <code>0 <= b1, b2, b3, b4 <= 255</code>,
- * then the result is equal to:
- * <ul><code>
- * (b1 << 24) | (b2 << 16) + (b3 << 8) + b4
- * </code></ul>
- * <p/>
- * This method blocks until the four bytes are read, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return the next four bytes of this file, interpreted as an
- * <code>int</code>.
- * @throws EOFException if this file reaches the end before reading
- * four bytes.
- * @throws IOException if an I/O error occurs.
- */
- public final int readInt() throws IOException {
- int ch1 = this.read();
- int ch2 = this.read();
- int ch3 = this.read();
- int ch4 = this.read();
- if ((ch1 | ch2 | ch3 | ch4) < 0) {
- throw new EOFException();
- }
- if (bigEndian) {
- return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4));
- } else {
- return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1));
- }
- }
- /**
- * Read an integer at the given position, bypassing all buffering.
- *
- * @param pos read a byte at this position
- * @return The int that was read
- * @throws IOException if an I/O error occurs.
- */
- public final int readIntUnbuffered(long pos) throws IOException {
- byte[] bb = new byte[4];
- read_(pos, bb, 0, 4);
- int ch1 = bb[0] & 0xff;
- int ch2 = bb[1] & 0xff;
- int ch3 = bb[2] & 0xff;
- int ch4 = bb[3] & 0xff;
- if ((ch1 | ch2 | ch3 | ch4) < 0) {
- throw new EOFException();
- }
- if (bigEndian) {
- return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4));
- } else {
- return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1));
- }
- }
- /**
- * Read an array of ints
- *
- * @param pa read into this array
- * @param start starting at pa[start]
- * @param n read this many elements
- * @throws IOException on read error
- */
- public final void readInt(int[] pa, int start, int n) throws IOException {
- for (int i = 0; i < n; i++) {
- pa[start + i] = readInt();
- }
- }
- /**
- * Reads a signed 64-bit integer from this file. This method reads eight
- * bytes from the file. If the bytes read, in order, are
- * <code>b1</code>, <code>b2</code>, <code>b3</code>,
- * <code>b4</code>, <code>b5</code>, <code>b6</code>,
- * <code>b7</code>, and <code>b8,</code> where:
- * <ul><code>
- * 0 <= b1, b2, b3, b4, b5, b6, b7, b8 <=255,
- * </code></ul>
- * <p/>
- * then the result is equal to:
- * <p><blockquote><pre>
- * ((long)b1 << 56) + ((long)b2 << 48)
- * + ((long)b3 << 40) + ((long)b4 << 32)
- * + ((long)b5 << 24) + ((long)b6 << 16)
- * + ((long)b7 << 8) + b8
- * </pre></blockquote>
- * <p/>
- * This method blocks until the eight bytes are read, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return the next eight bytes of this file, interpreted as a
- * <code>long</code>.
- * @throws EOFException if this file reaches the end before reading
- * eight bytes.
- * @throws IOException if an I/O error occurs.
- */
- public final long readLong() throws IOException {
- if (bigEndian) {
- return ((long) (readInt()) << 32) + (readInt() & 0xFFFFFFFFL); // tested ok
- } else {
- return ((readInt() & 0xFFFFFFFFL) + ((long) readInt() << 32)); // not tested yet ??
- }
- /* int ch1 = this.read();
- int ch2 = this.read();
- int ch3 = this.read();
- int ch4 = this.read();
- int ch5 = this.read();
- int ch6 = this.read();
- int ch7 = this.read();
- int ch8 = this.read();
- if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0)
- throw new EOFException();
- if (bigEndian)
- return ((long)(ch1 << 56)) + (ch2 << 48) + (ch3 << 40) + (ch4 << 32) + (ch5 << 24) + (ch6 << 16) + (ch7 << 8) + (ch8 << 0));
- else
- return ((long)(ch8 << 56) + (ch7 << 48) + (ch6 << 40) + (ch5 << 32) + (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));
- */
- }
- /**
- * Read an array of longs
- *
- * @param pa read into this array
- * @param start starting at pa[start]
- * @param n read this many elements
- * @throws IOException on read error
- */
- public final void readLong(long[] pa, int start, int n) throws IOException {
- for (int i = 0; i < n; i++) {
- pa[start + i] = readLong();
- }
- }
- /**
- * Reads a <code>float</code> from this file. This method reads an
- * <code>int</code> value as if by the <code>readInt</code> method
- * and then converts that <code>int</code> to a <code>float</code>
- * using the <code>intBitsToFloat</code> method in class
- * <code>Float</code>.
- * <p/>
- * This method blocks until the four bytes are read, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return the next four bytes of this file, interpreted as a
- * <code>float</code>.
- * @throws EOFException if this file reaches the end before reading
- * four bytes.
- * @throws IOException if an I/O error occurs.
- * @see java.io.RandomAccessFile#readInt()
- * @see java.lang.Float#intBitsToFloat(int)
- */
- public final float readFloat() throws IOException {
- return Float.intBitsToFloat(readInt());
- }
- /**
- * Read an array of floats
- *
- * @param pa read into this array
- * @param start starting at pa[start]
- * @param n read this many elements
- * @throws IOException on read error
- */
- public final void readFloat(float[] pa, int start, int n) throws IOException {
- for (int i = 0; i < n; i++) {
- pa[start + i] = Float.intBitsToFloat(readInt());
- }
- }
- /**
- * Reads a <code>double</code> from this file. This method reads a
- * <code>long</code> value as if by the <code>readLong</code> method
- * and then converts that <code>long</code> to a <code>double</code>
- * using the <code>longBitsToDouble</code> method in
- * class <code>Double</code>.
- * <p/>
- * This method blocks until the eight bytes are read, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return the next eight bytes of this file, interpreted as a
- * <code>double</code>.
- * @throws EOFException if this file reaches the end before reading
- * eight bytes.
- * @throws IOException if an I/O error occurs.
- * @see java.io.RandomAccessFile#readLong()
- * @see java.lang.Double#longBitsToDouble(long)
- */
- public final double readDouble() throws IOException {
- return Double.longBitsToDouble(readLong());
- }
- /**
- * Read an array of doubles
- *
- * @param pa read into this array
- * @param start starting at pa[start]
- * @param n read this many elements
- * @throws IOException on read error
- */
- public final void readDouble(double[] pa, int start, int n) throws IOException {
- for (int i = 0; i < n; i++) {
- pa[start + i] = Double.longBitsToDouble(readLong());
- }
- }
- /**
- * Reads the next line of text from this file. This method
- * successively reads bytes from the file until it reaches the end of
- * a line of text.
- * <p/>
- * <p/>
- * A line of text is terminated by a carriage-return character
- * (<code>'\r'</code>), a newline character (<code>'\n'</code>), a
- * carriage-return character immediately followed by a newline
- * character, or the end of the input stream. The line-terminating
- * character(s), if any, are included as part of the string returned.
- * <p/>
- * <p/>
- * This method blocks until a newline character is read, a carriage
- * return and the byte following it are read (to see if it is a
- * newline), the end of the stream is detected, or an exception is thrown.
- *
- * @return the next line of text from this file.
- * @throws IOException if an I/O error occurs.
- */
- public final String readLine() throws IOException {
- StringBuilder input = new StringBuilder();
- int c;
- while (((c = read()) != -1) && (c != '\n')) {
- input.append((char) c);
- }
- if ((c == -1) && (input.length() == 0)) {
- return null;
- }
- return input.toString();
- }
- /**
- * Reads in a string from this file. The string has been encoded
- * using a modified UTF-8 format.
- * <p/>
- * The first two bytes are read as if by
- * <code>readUnsignedShort</code>. This value gives the number of
- * following bytes that are in the encoded string, not
- * the length of the resulting string. The following bytes are then
- * interpreted as bytes encoding characters in the UTF-8 format
- * and are converted into characters.
- * <p/>
- * This method blocks until all the bytes are read, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return a Unicode string.
- * @throws EOFException if this file reaches the end before
- * reading all the bytes.
- * @throws IOException if an I/O error occurs.
- * @throws UTFDataFormatException if the bytes do not represent
- * valid UTF-8 encoding of a Unicode string.
- * @see java.io.RandomAccessFile#readUnsignedShort()
- */
- public final String readUTF() throws IOException {
- return DataInputStream.readUTF(this);
- }
- /**
- * Read a String of knoen length.
- *
- * @param nbytes number of bytes to read
- * @return String wrapping the bytes.
- * @throws IOException if an I/O error occurs.
- */
- public String readString(int nbytes) throws IOException {
- byte[] data = new byte[nbytes];
- readFully(data);
- return new String(data);
- }
- //
- // DataOutput methods.
- //
- /**
- * Writes a <code>boolean</code> to the file as a 1-byte value. The
- * value <code>true</code> is written out as the value
- * <code>(byte)1</code>; the value <code>false</code> is written out
- * as the value <code>(byte)0</code>.
- *
- * @param v a <code>boolean</code> value to be written.
- * @throws IOException if an I/O error occurs.
- */
- public final void writeBoolean(boolean v) throws IOException {
- write(v ? 1 : 0);
- }
- /**
- * Write an array of booleans
- *
- * @param pa write from this array
- * @param start starting with this element in the array
- * @param n write this number of elements
- * @throws IOException on read error
- */
- public final void writeBoolean(boolean[] pa, int start, int n) throws IOException {
- for (int i = 0; i < n; i++) {
- writeBoolean(pa[start + i]);
- }
- }
- /**
- * Writes a <code>byte</code> to the file as a 1-byte value.
- *
- * @param v a <code>byte</code> value to be written.
- * @throws IOException if an I/O error occurs.
- */
- public final void writeByte(int v) throws IOException {
- write(v);
- }
- /**
- * Writes a <code>short</code> to the file as two bytes, high byte first.
- *
- * @param v a <code>short</code> to be written.
- * @throws IOException if an I/O error occurs.
- */
- public final void writeShort(int v) throws IOException {
- write((v >>> 8) & 0xFF);
- write((v) & 0xFF);
- }
- /**
- * Write an array of shorts
- *
- * @param pa write from this array
- * @param start starting with this element in the array
- * @param n this number of elements
- * @throws IOException on read error
- */
- public final void writeShort(short[] pa, int start, int n) throws IOException {
- for (int i = 0; i < n; i++) {
- writeShort(pa[start + i]);
- }
- }
- /**
- * Writes a <code>char</code> to the file as a 2-byte value, high
- * byte first.
- *
- * @param v a <code>char</code> value to be written.
- * @throws IOException if an I/O error occurs.
- */
- public final void writeChar(int v) throws IOException {
- write((v >>> 8) & 0xFF);
- write((v) & 0xFF);
- }
- /**
- * Write an array of chars
- *
- * @param pa write from this array
- * @param start starting with this element in the array
- * @param n this number of elements
- * @throws IOException on read error
- */
- public final void writeChar(char[] pa, int start, int n) throws IOException {
- for (int i = 0; i < n; i++) {
- writeChar(pa[start + i]);
- }
- }
- /**
- * Writes an <code>int</code> to the file as four bytes, high byte first.
- *
- * @param v an <code>int</code> to be written.
- * @throws IOException if an I/O error occurs.
- */
- public final void writeInt(int v) throws IOException {
- write((v >>> 24) & 0xFF);
- write((v >>> 16) & 0xFF);
- write((v >>> 8) & 0xFF);
- write((v) & 0xFF);
- }
- /**
- * Write an array of ints
- *
- * @param pa write from this array
- * @param start starting with this element in the array
- * @param n write this number of elements
- * @throws IOException on read error
- */
- public final void writeInt(int[] pa, int start, int n) throws IOException {
- for (int i = 0; i < n; i++) {
- writeInt(pa[start + i]);
- }
- }
- /**
- * Writes a <code>long</code> to the file as eight bytes, high byte first.
- *
- * @param v a <code>long</code> to be written.
- * @throws IOException if an I/O error occurs.
- */
- public final void writeLong(long v) throws IOException {
- write((int) (v >>> 56) & 0xFF);
- write((int) (v >>> 48) & 0xFF);
- write((int) (v >>> 40) & 0xFF);
- write((int) (v >>> 32) & 0xFF);
- write((int) (v >>> 24) & 0xFF);
- write((int) (v >>> 16) & 0xFF);
- write((int) (v >>> 8) & 0xFF);
- write((int) (v) & 0xFF);
- }
- /**
- * Write an array of longs
- *
- * @param pa write from this array
- * @param start starting with this element in the array
- * @param n write this number of elements
- * @throws IOException on read error
- */
- public final void writeLong(long[] pa, int start, int n) throws IOException {
- for (int i = 0; i < n; i++) {
- writeLong(pa[start + i]);
- }
- }
- /**
- * Converts the float argument to an <code>int</code> using the
- * <code>floatToIntBits</code> method in class <code>Float</code>,
- * and then writes that <code>int</code> value to the file as a
- * 4-byte quantity, high byte first.
- *
- * @param v a <code>float</code> value to be written.
- * @throws IOException if an I/O error occurs.
- * @see java.lang.Float#floatToIntBits(float)
- */
- public final void writeFloat(float v) throws IOException {
- writeInt(Float.floatToIntBits(v));
- }
- /**
- * Write an array of floats
- *
- * @param pa write from this array
- * @param start starting with this element in the array
- * @param n write this number of elements
- * @throws IOException on read error
- */
- public final void writeFloat(float[] pa, int start, int n) throws IOException {
- for (int i = 0; i < n; i++) {
- writeFloat(pa[start + i]);
- }
- }
- /**
- * Converts the double argument to a <code>long</code> using the
- * <code>doubleToLongBits</code> method in class <code>Double</code>,
- * and then writes that <code>long</code> value to the file as an
- * 8-byte quantity, high byte first.
- *
- * @param v a <code>double</code> value to be written.
- * @throws IOException if an I/O error occurs.
- * @see java.lang.Double#doubleToLongBits(double)
- */
- public final void writeDouble(double v) throws IOException {
- writeLong(Double.doubleToLongBits(v));
- }
- /**
- * Write an array of doubles
- *
- * @param pa write from this array
- * @param start starting with this element in the array
- * @param n write this number of elements
- * @throws IOException on read error
- */
- public final void writeDouble(double[] pa, int start, int n) throws IOException {
- for (int i = 0; i < n; i++) {
- writeDouble(pa[start + i]);
- }
- }
- /**
- * Writes the string to the file as a sequence of bytes. Each
- * character in the string is written out, in sequence, by discarding
- * its high eight bits.
- *
- * @param s a string of bytes to be written.
- * @throws IOException if an I/O error occurs.
- */
- public final void writeBytes(String s) throws IOException {
- int len = s.length();
- for (int i = 0; i < len; i++) {
- write((byte) s.charAt(i));
- }
- }
- /**
- * Writes the character array to the file as a sequence of bytes. Each
- * character in the string is written out, in sequence, by discarding
- * its high eight bits.
- *
- * @param b a character array of bytes to be written.
- * @param off the index of the first character to write.
- * @param len the number of characters to write.
- * @throws IOException if an I/O error occurs.
- */
- public final void writeBytes(char b[], int off, int len) throws IOException {
- for (int i = off; i < len; i++) {
- write((byte) b[i]);
- }
- }
- /**
- * Writes a string to the file as a sequence of characters. Each
- * character is written to the data output stream as if by the
- * <code>writeChar</code> method.
- *
- * @param s a <code>String</code> value to be written.
- * @throws IOException if an I/O error occurs.
- * @see java.io.RandomAccessFile#writeChar(int)
- */
- public final void writeChars(String s) throws IOException {
- int len = s.length();
- for (int i = 0; i < len; i++) {
- int v = s.charAt(i);
- write((v >>> 8) & 0xFF);
- write((v) & 0xFF);
- }
- }
- /**
- * Writes a string to the file using UTF-8 encoding in a
- * machine-independent manner.
- * <p/>
- * First, two bytes are written to the file as if by the
- * <code>writeShort</code> method giving the number of bytes to
- * follow. This value is the number of bytes actually written out,
- * not the length of the string. Following the length, each character
- * of the string is output, in sequence, using the UTF-8 encoding
- * for each character.
- *
- * @param str a string to be written.
- * @throws IOException if an I/O error occurs.
- */
- public final void writeUTF(String str) throws IOException {
- int strlen = str.length();
- int utflen = 0;
- for (int i = 0; i < strlen; i++) {
- int c = str.charAt(i);
- if ((c >= 0x0001) && (c <= 0x007F)) {
- utflen++;
- } else if (c > 0x07FF) {
- utflen += 3;
- } else {
- utflen += 2;
- }
- }
- if (utflen > 65535) {
- throw new UTFDataFormatException();
- }
- write((utflen >>> 8) & 0xFF);
- write((utflen) & 0xFF);
- for (int i = 0; i < strlen; i++) {
- int c = str.charAt(i);
- if ((c >= 0x0001) && (c <= 0x007F)) {
- write(c);
- } else if (c > 0x07FF) {
- write(0xE0 | ((c >> 12) & 0x0F));
- write(0x80 | ((c >> 6) & 0x3F));
- write(0x80 | ((c) & 0x3F));
- } else {
- write(0xC0 | ((c >> 6) & 0x1F));
- write(0x80 | ((c) & 0x3F));
- }
- }
- }
- /**
- * Create a string representation of this object.
- *
- * @return a string representation of the state of the object.
- */
- public String toString() {
- return "fp=" + filePosition + ", bs=" + bufferStart + ", de="
- + dataEnd + ", ds=" + dataSize + ", bl=" + buffer.length
- + ", readonly=" + readonly + ", bm=" + bufferModified;
- }
- /////////////////////////////////////////////////
- /**
- * Search forward from the current pos, looking for a match.
- *
- * @param match the match to look for.
- * @param maxBytes maximum number of bytes to search. use -1 for all
- * @return true if found, file position will be at the start of the match.
- * @throws IOException on read error
- */
- public boolean searchForward(KMPMatch match, int maxBytes) throws IOException {
- long start = getFilePointer();
- long last = (maxBytes < 0) ? length() : Math.min(length(), start + maxBytes);
- long needToScan = last - start;
- // check what ever is now in the buffer
- int bytesAvailable = (int) (dataEnd - filePosition);
- if (bytesAvailable < 1) {
- seek(filePosition); // read a new buffer
- bytesAvailable = (int) (dataEnd - filePosition);
- }
- int bufStart = (int) (filePosition - bufferStart);
- int scanBytes = (int) Math.min(bytesAvailable, needToScan);
- int pos = match.indexOf(buffer, bufStart, scanBytes);
- if (pos >= 0) {
- seek(bufferStart + pos);
- return true;
- }
- int matchLen = match.getMatchLength();
- needToScan -= scanBytes - matchLen;
- while (needToScan > matchLen) {
- readBuffer(dataEnd - matchLen); // force new buffer
- scanBytes = (int) Math.min(buffer.length, needToScan);
- pos = match.indexOf(buffer, 0, scanBytes);
- if (pos > 0) {
- seek(bufferStart + pos);
- return true;
- }
- needToScan -= scanBytes - matchLen;
- }
- // failure
- seek(last);
- return false;
- }
- }
|