ASF Bugzilla – Attachment 15774 Details for
Bug 31906
[PATCH] "Pull" method for handeling continue records
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
The new RecordInputStream class
RecordInputStream.java (text/plain), 8.70 KB, created by
Jason Height
on 2005-07-26 09:31:54 UTC
(
hide
)
Description:
The new RecordInputStream class
Filename:
MIME Type:
Creator:
Jason Height
Created:
2005-07-26 09:31:54 UTC
Size:
8.70 KB
patch
obsolete
> >/* ==================================================================== > Copyright 2002-2004 Apache Software Foundation > > Licensed under the Apache License, Version 2.0 (the "License"); > you may not use this file except in compliance with the License. > You may obtain a copy of the License at > > http://www.apache.org/licenses/LICENSE-2.0 > > Unless required by applicable law or agreed to in writing, software > distributed under the License is distributed on an "AS IS" BASIS, > WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > See the License for the specific language governing permissions and > limitations under the License. >==================================================================== */ > > >package org.apache.poi.hssf.record; > >import org.apache.poi.util.LittleEndian; > >import java.io.IOException; >import java.io.InputStream; >import java.io.ByteArrayOutputStream; >import java.lang.reflect.Constructor; >import java.util.*; > >/** > * Title: Record Input Stream<P> > * Description: Wraps a stream and provides helper methods for the construction of records.<P> > * > * @author Jason Height (jheight @ apache dot org) > */ > >public class RecordInputStream extends InputStream >{ > /** Maximum size of a single record (minus the 4 byte header) without a continue*/ > public final static short MAX_RECORD_DATA_SIZE = 8224; > > private InputStream in; > private short currentSid; > private short currentLength = -1; > private short nextSid = -1; > > private byte[] data = new byte[MAX_RECORD_DATA_SIZE]; > private short recordOffset; > private long pos; > > private boolean autoContinue = true; > > public RecordInputStream(InputStream in) throws RecordFormatException { > this.in = in; > try { > nextSid = LittleEndian.readShort(in); > //Dont increment the pos just yet (technically we are at the start of > //the record stream until nextRecord is called). > } catch (IOException ex) { > throw new RecordFormatException("Error reading bytes"); > } > } > > /** This method will read a byte from the current record*/ > public int read() throws IOException { > checkRecordPosition(); > > byte result = data[recordOffset]; > recordOffset += 1; > pos += 1; > return result; > } > > public short getSid() { > return currentSid; > } > > public short getLength() { > return currentLength; > } > > public short getRecordOffset() { > return recordOffset; > } > > public long getPos() { > return pos; > } > > public boolean hasNextRecord() { > return (nextSid != 0); > } > > /** Moves to the next record in the stream. > * > * <i>Note: The auto continue flag is reset to true</i> > */ > > public void nextRecord() throws RecordFormatException { > if ((currentLength != -1) && (currentLength != recordOffset)) { > System.out.println("WARN. Unread "+remaining()+" bytes of record "+Integer.toHexString(currentSid)); > } > currentSid = nextSid; > pos += LittleEndian.SHORT_SIZE; > autoContinue = true; > try { > recordOffset = 0; > currentLength = LittleEndian.readShort(in); > if (currentLength > MAX_RECORD_DATA_SIZE) > throw new RecordFormatException("The content of an excel record cannot exceed "+MAX_RECORD_DATA_SIZE+" bytes"); > pos += LittleEndian.SHORT_SIZE; > in.read(data, 0, currentLength); > > //Read the Sid of the next record > nextSid = LittleEndian.readShort(in); > } catch (IOException ex) { > throw new RecordFormatException("Error reading bytes"); > } > } > > public void setAutoContinue(boolean enable) { > this.autoContinue = enable; > } > > public boolean getAutoContinue() { > return autoContinue; > } > > protected void checkRecordPosition() { > if (remaining() <= 0) { > if (isContinueNext() && autoContinue) { > nextRecord(); > } > else throw new ArrayIndexOutOfBoundsException(); > } > } > > public byte readByte() { > checkRecordPosition(); > > byte result = data[recordOffset]; > recordOffset += 1; > pos += 1; > return result; > } > > public short readShort() { > checkRecordPosition(); > > short result = LittleEndian.getShort(data, recordOffset); > recordOffset += LittleEndian.SHORT_SIZE; > pos += LittleEndian.SHORT_SIZE; > return result; > } > > public int readInt() { > checkRecordPosition(); > > int result = LittleEndian.getInt(data, recordOffset); > recordOffset += LittleEndian.INT_SIZE; > pos += LittleEndian.INT_SIZE; > return result; > } > > public long readLong() { > checkRecordPosition(); > > long result = LittleEndian.getLong(data, recordOffset); > recordOffset += LittleEndian.LONG_SIZE; > pos += LittleEndian.LONG_SIZE; > return result; > } > > public int readUShort() { > checkRecordPosition(); > > int result = LittleEndian.getUShort(data, recordOffset); > recordOffset += LittleEndian.SHORT_SIZE; > pos += LittleEndian.SHORT_SIZE; > return result; > } > > byte[] NAN_data = null; > public double readDouble() { > checkRecordPosition(); > //Reset NAN data > NAN_data = null; > double result = LittleEndian.getDouble(data, recordOffset); > //Excel represents NAN in several ways, at this point in time we do not often > //know the sequence of bytes, so as a hack we store the NAN byte sequence > //so that it is not corrupted. > if (Double.isNaN(result)) { > NAN_data = new byte[8]; > System.arraycopy(data, recordOffset, NAN_data, 0, 8); > } > > recordOffset += LittleEndian.DOUBLE_SIZE; > pos += LittleEndian.DOUBLE_SIZE; > return result; > } > > public byte[] getNANData() { > if (NAN_data == null) > throw new RecordFormatException("Do NOT call getNANData without calling readDouble that returns NaN"); > return NAN_data; > } > > public short[] readShortArray() { > checkRecordPosition(); > > short[] arr = LittleEndian.getShortArray(data, recordOffset); > final int size = (2 * (arr.length +1)); > recordOffset += size; > pos += size; > > return arr; > } > > /** > * given a byte array of 16-bit unicode characters, compress to 8-bit and > * return a string > * > * { 0x16, 0x00 } -0x16 > * > * @param len the length of the final string > * @return the converted string > * @exception IllegalArgumentException if len is too large (i.e., > * there is not enough data in string to create a String of that > * length) > */ > public String readUnicodeLEString(int length) { > if ((length < 0) || ((remaining() / 2) < length)) { > throw new IllegalArgumentException("Illegal length"); > } > > StringBuffer buf = new StringBuffer(length); > for (int i=0;i<length;i++) { > if ((remaining() == 0) && (isContinueNext())) > nextRecord(); > char ch = (char)readShort(); > buf.append(ch); > } > return buf.toString(); > } > > public String readCompressedUnicode(int length) { > if ((length < 0) || (remaining() < length)) { > throw new IllegalArgumentException("Illegal length"); > } > > StringBuffer buf = new StringBuffer(length); > for (int i=0;i<length;i++) { > if ((remaining() == 0) && (isContinueNext())) > nextRecord(); > char ch = (char)readByte(); > buf.append(ch); > } > return buf.toString(); > } > > public UnicodeString readUnicodeString() { > return new UnicodeString(this); > } > > public byte[] readRemainder() { > int size = remaining(); > byte[] result = new byte[size]; > System.arraycopy(data, recordOffset, result, 0, size); > recordOffset += size; > pos += size; > return result; > } > > /** Reads all byte data for the current record, including any > * that overlaps into any following continue records. > * > * @deprecated Best to write a input stream that wraps this one where there is > * special sub record that may overlap continue records. > */ > public byte[] readAllContinuedRemainder() { > //Using a ByteArrayOutputStream is just an easy way to get a > //growable array of the data. > ByteArrayOutputStream out = new ByteArrayOutputStream(2*MAX_RECORD_DATA_SIZE); > > while (isContinueNext()) { > byte[] b = readRemainder(); > out.write(b, 0, b.length); > nextRecord(); > } > byte[] b = readRemainder(); > out.write(b, 0, b.length); > > return out.toByteArray(); > } > > public int remaining() { > return (currentLength - recordOffset); > } > > public boolean isContinueNext() { > return (nextSid == ContinueRecord.sid); > } >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 31906
:
13227
|
13228
|
15726
|
15773
| 15774 |
15775