You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2018/09/14 21:35:43 UTC

svn commit: r1840955 - in /poi/branches/hemf/src/java/org/apache/poi: hssf/dev/BiffViewer.java hssf/record/RecordInputStream.java util/IOUtils.java util/LittleEndianInputStream.java

Author: kiwiwings
Date: Fri Sep 14 21:35:43 2018
New Revision: 1840955

URL: http://svn.apache.org/viewvc?rev=1840955&view=rev
Log:
Buffered LittleEndianInputStream

Modified:
    poi/branches/hemf/src/java/org/apache/poi/hssf/dev/BiffViewer.java
    poi/branches/hemf/src/java/org/apache/poi/hssf/record/RecordInputStream.java
    poi/branches/hemf/src/java/org/apache/poi/util/IOUtils.java
    poi/branches/hemf/src/java/org/apache/poi/util/LittleEndianInputStream.java

Modified: poi/branches/hemf/src/java/org/apache/poi/hssf/dev/BiffViewer.java
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/java/org/apache/poi/hssf/dev/BiffViewer.java?rev=1840955&r1=1840954&r2=1840955&view=diff
==============================================================================
--- poi/branches/hemf/src/java/org/apache/poi/hssf/dev/BiffViewer.java (original)
+++ poi/branches/hemf/src/java/org/apache/poi/hssf/dev/BiffViewer.java Fri Sep 14 21:35:43 2018
@@ -527,20 +527,16 @@ public final class BiffViewer {
 		}
 		@Override
 		public int read(byte[] b, int off, int len) throws IOException {
+            if (b == null || off < 0 || len < 0  || b.length < off+len) {
+                throw new IllegalArgumentException();
+            }
 			if (_currentPos >= _currentSize) {
 				fillNextBuffer();
 			}
 			if (_currentPos >= _currentSize) {
 				return -1;
 			}
-			int availSize = _currentSize - _currentPos;
-			int result;
-			if (len > availSize) {
-				System.err.println("Unexpected request to read past end of current biff record");
-				result = availSize;
-			} else {
-				result = len;
-			}
+			final int result = Math.min(len, _currentSize - _currentPos);
 			System.arraycopy(_data, _currentPos, b, off, result);
 			_currentPos += result;
 			_overallStreamPos += result;

Modified: poi/branches/hemf/src/java/org/apache/poi/hssf/record/RecordInputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/java/org/apache/poi/hssf/record/RecordInputStream.java?rev=1840955&r1=1840954&r2=1840955&view=diff
==============================================================================
--- poi/branches/hemf/src/java/org/apache/poi/hssf/record/RecordInputStream.java (original)
+++ poi/branches/hemf/src/java/org/apache/poi/hssf/record/RecordInputStream.java Fri Sep 14 21:35:43 2018
@@ -105,8 +105,8 @@ public final class RecordInputStream imp
 
 		private final LittleEndianInput _lei;
 
-		public SimpleHeaderInput(InputStream in) {
-			_lei = getLEI(in);
+		private SimpleHeaderInput(LittleEndianInput lei) {
+			_lei = lei;
 		}
 		@Override
         public int available() {
@@ -128,8 +128,12 @@ public final class RecordInputStream imp
 
 	public RecordInputStream(InputStream in, EncryptionInfo key, int initialOffset) throws RecordFormatException {
 		if (key == null) {
-			_dataInput = getLEI(in);
-			_bhi = new SimpleHeaderInput(in);
+			_dataInput = (in instanceof LittleEndianInput)
+				// accessing directly is an optimisation
+				? (LittleEndianInput)in
+				// less optimal, but should work OK just the same. Often occurs in junit tests.
+				: new LittleEndianInputStream(in);
+			_bhi = new SimpleHeaderInput(_dataInput);
 		} else {
 			Biff8DecryptingStream bds = new Biff8DecryptingStream(in, initialOffset, key);
             _dataInput = bds;
@@ -138,15 +142,6 @@ public final class RecordInputStream imp
 		_nextSid = readNextSid();
 	}
 
-	static LittleEndianInput getLEI(InputStream is) {
-		if (is instanceof LittleEndianInput) {
-			// accessing directly is an optimisation
-			return (LittleEndianInput) is;
-		}
-		// less optimal, but should work OK just the same. Often occurs in junit tests.
-		return new LittleEndianInputStream(is);
-	}
-
 	/**
 	 * @return the number of bytes available in the current BIFF record
 	 * @see #remaining()
@@ -194,11 +189,9 @@ public final class RecordInputStream imp
 	private int readNextSid() {
 		int nAvailable  = _bhi.available();
 		if (nAvailable < EOFRecord.ENCODED_SIZE) {
-			if (nAvailable > 0) {
-				// some scrap left over?
-				// ex45582-22397.xls has one extra byte after the last record
-				// Excel reads that file OK
-			}
+			// some scrap left over, if nAvailable > 0?
+			// ex45582-22397.xls has one extra byte after the last record
+			// Excel reads that file OK
 			return INVALID_SID_VALUE;
 		}
 		int result = _bhi.readRecordSID();
@@ -302,17 +295,13 @@ public final class RecordInputStream imp
 		return _dataInput.readUShort();
 	}
 
+	/**
+	 *
+	 * @return a double - might return NaN
+	 */
 	@Override
     public double readDouble() {
-		long valueLongBits = readLong();
-		double result = Double.longBitsToDouble(valueLongBits);
-		if (Double.isNaN(result)) {
-            // YK: Excel doesn't write NaN but instead converts the cell type into {@link CellType#ERROR}.
-            // HSSF prior to version 3.7 had a bug: it could write Double.NaN but could not read such a file back.
-            // This behavior was fixed in POI-3.7.
-            //throw new RuntimeException("Did not expect to read NaN"); // (Because Excel typically doesn't write NaN)
-		}
-		return result;
+		return Double.longBitsToDouble(readLong());
 	}
 	
 	public void readPlain(byte[] buf, int off, int len) {
@@ -329,7 +318,7 @@ public final class RecordInputStream imp
         readFully(buf, off, len, false);
     }
 	
-    protected void readFully(byte[] buf, int off, int len, boolean isPlain) {
+    private void readFully(byte[] buf, int off, int len, boolean isPlain) {
 	    int origLen = len;
 	    if (buf == null) {
 	        throw new NullPointerException();

Modified: poi/branches/hemf/src/java/org/apache/poi/util/IOUtils.java
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/java/org/apache/poi/util/IOUtils.java?rev=1840955&r1=1840954&r2=1840955&view=diff
==============================================================================
--- poi/branches/hemf/src/java/org/apache/poi/util/IOUtils.java (original)
+++ poi/branches/hemf/src/java/org/apache/poi/util/IOUtils.java Fri Sep 14 21:35:43 2018
@@ -50,6 +50,7 @@ public final class IOUtils {
      * @param maxOverride The number of bytes that should be possible to be allocated in one step.
      * @since 4.0.0
      */
+    @SuppressWarnings("unused")
     public static void setByteArrayMaxOverride(int maxOverride) {
         BYTE_ARRAY_MAX_OVERRIDE = maxOverride;
     }
@@ -395,13 +396,35 @@ public final class IOUtils {
      * @throws IOException If copying the data fails.
      */
     public static long copy(InputStream inp, OutputStream out) throws IOException {
+        return copy(inp, out, -1);
+    }
+
+    /**
+     * Copies all the data from the given InputStream to the OutputStream. It
+     * leaves both streams open, so you will still need to close them once done.
+     *
+     * @param inp The {@link InputStream} which provides the data
+     * @param out The {@link OutputStream} to write the data to
+     * @param limit limit the copied bytes - use {@code -1} for no limit
+     * @return the amount of bytes copied
+     *
+     * @throws IOException If copying the data fails.
+     */
+    public static long copy(InputStream inp, OutputStream out, long limit) throws IOException {
         final byte[] buff = new byte[4096];
         long totalCount = 0;
-        for (int count; (count = inp.read(buff)) != -1; totalCount += count) {
-            if (count > 0) {
-                out.write(buff, 0, count);
+        int readBytes = -1;
+        do {
+            int todoBytes = (int)((limit < 0) ? buff.length : Math.min(limit-totalCount, buff.length));
+            if (todoBytes > 0) {
+                readBytes = inp.read(buff, 0, todoBytes);
+                if (readBytes > 0) {
+                    out.write(buff, 0, readBytes);
+                    totalCount += readBytes;
+                }
             }
-        }
+        } while (readBytes >= 0 && (limit == -1 || totalCount < limit));
+
         return totalCount;
     }
 

Modified: poi/branches/hemf/src/java/org/apache/poi/util/LittleEndianInputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/java/org/apache/poi/util/LittleEndianInputStream.java?rev=1840955&r1=1840954&r2=1840955&view=diff
==============================================================================
--- poi/branches/hemf/src/java/org/apache/poi/util/LittleEndianInputStream.java (original)
+++ poi/branches/hemf/src/java/org/apache/poi/util/LittleEndianInputStream.java Fri Sep 14 21:35:43 2018
@@ -17,6 +17,7 @@
 
 package org.apache.poi.util;
 
+import java.io.BufferedInputStream;
 import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -29,12 +30,16 @@ import java.io.InputStream;
  */
 public class LittleEndianInputStream extends FilterInputStream implements LittleEndianInput {
 
+	private static final int BUFFERED_SIZE = 8096;
+
 	private static final int EOF = -1;
+	private int readIndex = 0;
+	private int markIndex = -1;
 
 	public LittleEndianInputStream(InputStream is) {
-		super(is);
+		super(is.markSupported() ? is : new BufferedInputStream(is, BUFFERED_SIZE));
 	}
-	
+
 	@Override
 	@SuppressForbidden("just delegating")
 	public int available() {
@@ -60,7 +65,18 @@ public class LittleEndianInputStream ext
 		}
 		return LittleEndian.getUByte(buf);
 	}
-	
+
+	/**
+	 * get a float value, reads it in little endian format
+	 * then converts the resulting revolting IEEE 754 (curse them) floating
+	 * point number to a happy java float
+	 *
+	 * @return the float (32-bit) value
+	 */
+	public float readFloat() {
+		return Float.intBitsToFloat( readInt() );
+	}
+
 	@Override
 	public double readDouble() {
 		return Double.longBitsToDouble(readLong());
@@ -137,14 +153,42 @@ public class LittleEndianInputStream ext
         }
     }
 
-    //Makes repeated calls to super.read() until length is read or EOF is reached
+	@Override
+	public int read(byte[] b, int off, int len) throws IOException {
+    	int readBytes = super.read(b, off, len);
+		readIndex += readBytes;
+		return readBytes;
+	}
+
+	@Override
+	public synchronized void mark(int readlimit) {
+		super.mark(readlimit);
+		markIndex = readIndex;
+	}
+
+	@Override
+	public synchronized void reset() throws IOException {
+		super.reset();
+		if (markIndex > -1) {
+			readIndex = markIndex;
+			markIndex = -1;
+		}
+	}
+
+	public int getReadIndex() {
+		return readIndex;
+	}
+
+
+
+	//Makes repeated calls to super.read() until length is read or EOF is reached
 	private int _read(byte[] buffer, int offset, int length) throws IOException {
     	//lifted directly from org.apache.commons.io.IOUtils 2.4
 		int remaining = length;
 		while (remaining > 0) {
 			int location = length - remaining;
 			int count = read(buffer, offset + location, remaining);
-			if (EOF == count) { // EOF
+			if (EOF == count) {
 				break;
 			}
 			remaining -= count;
@@ -157,4 +201,9 @@ public class LittleEndianInputStream ext
     public void readPlain(byte[] buf, int off, int len) {
         readFully(buf, off, len);
     }
+
+
+	public void skipFully(int len) throws IOException {
+		IOUtils.skipFully(this, len);
+	}
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org