mirror of https://github.com/apache/poi.git
bug 52949: add junit test for RLEDecompressingInputStream
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1738436 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
46a29e4a24
commit
17a339549d
|
@ -48,8 +48,8 @@ import org.apache.poi.poifs.storage.SmallBlockTableReader;
|
|||
|
||||
public class POIFSReader
|
||||
{
|
||||
private POIFSReaderRegistry registry;
|
||||
private boolean registryClosed;
|
||||
private final POIFSReaderRegistry registry;
|
||||
private boolean registryClosed;
|
||||
|
||||
/**
|
||||
* Create a POIFSReader
|
||||
|
|
|
@ -31,9 +31,9 @@ import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
|
|||
|
||||
public class POIFSReaderEvent
|
||||
{
|
||||
private DocumentInputStream stream;
|
||||
private POIFSDocumentPath path;
|
||||
private String documentName;
|
||||
private final DocumentInputStream stream;
|
||||
private final POIFSDocumentPath path;
|
||||
private final String documentName;
|
||||
|
||||
/**
|
||||
* package scoped constructor
|
||||
|
|
|
@ -35,8 +35,8 @@ public class POIFSDocumentPath
|
|||
{
|
||||
private static final POILogger log = POILogFactory.getLogger(POIFSDocumentPath.class);
|
||||
|
||||
private String[] components;
|
||||
private int hashcode = 0;
|
||||
private final String[] components;
|
||||
private int hashcode = 0; //lazy-compute hashCode
|
||||
|
||||
/**
|
||||
* constructor for the path of a document that is not in the root
|
||||
|
@ -199,14 +199,20 @@ public class POIFSDocumentPath
|
|||
{
|
||||
if (hashcode == 0)
|
||||
{
|
||||
for (int j = 0; j < components.length; j++)
|
||||
{
|
||||
hashcode += components[ j ].hashCode();
|
||||
}
|
||||
hashcode = computeHashCode();
|
||||
}
|
||||
return hashcode;
|
||||
}
|
||||
|
||||
private int computeHashCode() {
|
||||
int code = 0;
|
||||
for (int j = 0; j < components.length; j++)
|
||||
{
|
||||
code += components[ j ].hashCode();
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of components
|
||||
*/
|
||||
|
@ -249,16 +255,32 @@ public class POIFSDocumentPath
|
|||
{
|
||||
return null;
|
||||
}
|
||||
POIFSDocumentPath parent = new POIFSDocumentPath(null);
|
||||
String[] parentComponents = new String[ length ];
|
||||
System.arraycopy(components, 0, parentComponents, 0, length);
|
||||
POIFSDocumentPath parent = new POIFSDocumentPath(parentComponents);
|
||||
|
||||
parent.components = new String[ length ];
|
||||
System.arraycopy(components, 0, parent.components, 0, length);
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the last name in the document path's name sequence.
|
||||
* If the document path's name sequence is empty, then the empty string is returned.</p>
|
||||
*
|
||||
* @since 2016-04-09
|
||||
* @return The last name in the document path's name sequence, or empty string if this is the root path
|
||||
*/
|
||||
|
||||
public String getName()
|
||||
{
|
||||
if (components.length == 0) {
|
||||
return "";
|
||||
}
|
||||
return components[components.length - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns a string representation of the path. Components are
|
||||
* separated by the platform-specific file separator.</p>
|
||||
* separated by the platform-specific file separator {@link File#separatorChar}</p>
|
||||
*
|
||||
* @return string representation
|
||||
*
|
||||
|
|
|
@ -120,13 +120,18 @@ public final class IOUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Same as the normal <tt>in.read(b, off, len)</tt>, but tries to ensure
|
||||
* that the entire len number of bytes is read.
|
||||
* <p>
|
||||
* If the end of file is reached before any bytes are read, returns -1. If
|
||||
* <p>Same as the normal {@link InputStream#read(byte[], int, int)}, but tries to ensure
|
||||
* that the entire len number of bytes is read.</p>
|
||||
*
|
||||
* <p>If the end of file is reached before any bytes are read, returns <tt>-1</tt>. If
|
||||
* the end of the file is reached after some bytes are read, returns the
|
||||
* number of bytes read. If the end of the file isn't reached before len
|
||||
* bytes have been read, will return len bytes.
|
||||
* number of bytes read. If the end of the file isn't reached before <tt>len</tt>
|
||||
* bytes have been read, will return <tt>len</tt> bytes.</p>
|
||||
*
|
||||
* @param in the stream from which the data is read.
|
||||
* @param b the buffer into which the data is read.
|
||||
* @param off the start offset in array <tt>b</tt> at which the data is written.
|
||||
* @param len the maximum number of bytes to read.
|
||||
*/
|
||||
public static int readFully(InputStream in, byte[] b, int off, int len) throws IOException {
|
||||
int total = 0;
|
||||
|
|
|
@ -19,6 +19,8 @@ package org.apache.poi.util;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
/**
|
||||
* Wrapper of InputStream which provides Run Length Encoding (RLE)
|
||||
|
@ -270,4 +272,18 @@ public class RLEDecompressingInputStream extends InputStream {
|
|||
}
|
||||
return (b0 & 0xFF) | ((b1 & 0xFF) << 8) | ((b2 & 0xFF) << 16) | ((b3 & 0xFF) << 24);
|
||||
}
|
||||
|
||||
public static final byte[] decompress(byte[] compressed) throws IOException {
|
||||
return decompress(compressed, 0, compressed.length);
|
||||
}
|
||||
|
||||
public static final byte[] decompress(byte[] compressed, int offset, int length) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
InputStream instream = new ByteArrayInputStream(compressed, offset, length);
|
||||
InputStream stream = new RLEDecompressingInputStream(instream);
|
||||
IOUtils.copy(stream, out);
|
||||
stream.close();
|
||||
out.close();
|
||||
return out.toByteArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You 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.util;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class TestRLEDecompressingInputStream {
|
||||
|
||||
/**
|
||||
* Section 3.2.1 No Compression Example
|
||||
*
|
||||
* The following string illustrates an ASCII text string with a set of characters that cannot be compressed
|
||||
* by the compression algorithm specified in section 2.4.1.
|
||||
*
|
||||
* abcdefghijklmnopqrstuv.
|
||||
*
|
||||
* This example is provided to demonstrate the results of compressing and decompressing the string
|
||||
* using an interoperable implementation of the algorithm specified in section 2.4.1.
|
||||
*
|
||||
* The following hex array represents the compressed byte array of the example string as compressed by
|
||||
* the compression algorithm.
|
||||
*
|
||||
* 01 19 B0 00 61 62 63 64 65 66 67 68 00 69 6A 6B 6C
|
||||
* 6D 6E 6F 70 00 71 72 73 74 75 76 2E
|
||||
*
|
||||
* The following hex array represents the decompressed byte array of the example string as
|
||||
* decompressed by the decompression algorithm.
|
||||
*
|
||||
* 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71
|
||||
* 72 73 74 75 76 2E
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void noCompressionExample() {
|
||||
final byte[] compressed = {
|
||||
0x01, 0x19, (byte)0xB0, 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x00, 0x69, 0x6A, 0x6B, 0x6C,
|
||||
0x6D, 0x6E, 0x6F, 0x70, 0x00, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x2E
|
||||
};
|
||||
final String expected = "abcdefghijklmnopqrstuv.";
|
||||
checkRLEDecompression(expected, compressed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Section 3.2.2 Normal Compression Example
|
||||
*
|
||||
* The following string illustrates an ASCII text string with a typical set of characters that can be
|
||||
* compressed by the compression algorithm.
|
||||
*
|
||||
* #aaabcdefaaaaghijaaaaaklaaamnopqaaaaaaaaaaaarstuvwxyzaaa
|
||||
*
|
||||
* This example is provided to demonstrate the results of compressing and decompressing the example
|
||||
* string using an interoperable implementation of the algorithm specified in section 2.4.1.
|
||||
*
|
||||
* The following hex array represents the compressed byte array of the example string as compressed by
|
||||
* the compression algorithm:
|
||||
*
|
||||
* 01 2F B0 00 23 61 61 61 62 63 64 65 82 66 00 70
|
||||
* 61 67 68 69 6A 01 38 08 61 6B 6C 00 30 6D 6E 6F
|
||||
* 70 06 71 02 70 04 10 72 73 74 75 76 10 77 78 79
|
||||
* 7A 00 3C
|
||||
*
|
||||
* The following hex array represents the decompressed byte array of the example string as
|
||||
* decompressed by the decompression algorithm:
|
||||
*
|
||||
* 23 61 61 61 62 63 64 65 66 61 61 61 61 67 68 69
|
||||
* 6a 61 61 61 61 61 6B 6C 61 61 61 6D 6E 6F 70 71
|
||||
* 61 61 61 61 61 61 61 61 61 61 61 61 72 73 74 75
|
||||
* 76 77 78 79 7A 61 61 61
|
||||
*/
|
||||
@Test
|
||||
public void normalCompressionExample() {
|
||||
final byte[] compressed = {
|
||||
0x01, 0x2F, (byte)0xB0, 0x00, 0x23, 0x61, 0x61, 0x61, 0x62, 0x63, 0x64, 0x65, (byte)0x82, 0x66, 0x00, 0x70,
|
||||
0x61, 0x67, 0x68, 0x69, 0x6A, 0x01, 0x38, 0x08, 0x61, 0x6B, 0x6C, 0x00, 0x30, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x06, 0x71, 0x02, 0x70, 0x04, 0x10, 0x72, 0x73, 0x74, 0x75, 0x76, 0x10, 0x77, 0x78, 0x79,
|
||||
0x7A, 0x00, 0x3C
|
||||
};
|
||||
final String expected = "#aaabcdefaaaaghijaaaaaklaaamnopqaaaaaaaaaaaarstuvwxyzaaa";
|
||||
checkRLEDecompression(expected, compressed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Section 3.2.3 Maximum Compression Example
|
||||
*
|
||||
* The following string illustrates an ASCII text string with a typical set of characters that can be
|
||||
* compressed by the compression algorithm.
|
||||
*
|
||||
* aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
*
|
||||
* This example is provided to demonstrate the results of compressing and decompressing the example
|
||||
* string using an interoperable implementation of the algorithm specified in section 2.4.1.
|
||||
*
|
||||
* The following hex array represents the compressed byte array of the example string as compressed by
|
||||
* the compression algorithm:
|
||||
*
|
||||
* 01 03 B0 02 61 45 00
|
||||
*
|
||||
* The following hex array represents the decompressed byte array of the example string as
|
||||
* decompressed by the decompression algorithm:
|
||||
*
|
||||
* 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
|
||||
* 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
|
||||
* 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
|
||||
* 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
|
||||
* 61 61 61 61 61 61 61 61 61
|
||||
*/
|
||||
@Test
|
||||
public void maximumCompressionExample() {
|
||||
final byte[] compressed = {
|
||||
0x01, 0x03, (byte)0xB0, 0x02, 0x61, 0x45, 0x00
|
||||
};
|
||||
final String expected = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||
checkRLEDecompression(expected, compressed);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decompress() throws IOException {
|
||||
final byte[] compressed = {
|
||||
0x01, 0x03, (byte)0xB0, 0x02, 0x61, 0x45, 0x00
|
||||
};
|
||||
final byte[] expanded = RLEDecompressingInputStream.decompress(compressed);
|
||||
final byte[] expected = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".getBytes();
|
||||
assertArrayEquals(expected, expanded);
|
||||
}
|
||||
|
||||
private static void checkRLEDecompression(String expected, byte[] runLengthEncodedData) {
|
||||
InputStream compressedStream = new ByteArrayInputStream(runLengthEncodedData);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
try {
|
||||
InputStream stream = new RLEDecompressingInputStream(compressedStream);
|
||||
try {
|
||||
IOUtils.copy(stream, out);
|
||||
} finally {
|
||||
out.close();
|
||||
stream.close();
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
assertEquals(expected, out.toString());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue