fixed bug
This commit is contained in:
@@ -89,8 +89,8 @@ public class ZstdOutputStream extends OutputStream {
|
|||||||
public void write(byte[] arr, int off, int len) {
|
public void write(byte[] arr, int off, int len) {
|
||||||
int written = 0;
|
int written = 0;
|
||||||
while (written < len - off) {
|
while (written < len - off) {
|
||||||
int writeSize = Math.min(len, input.src.capacity() - input.src.position());
|
int writeSize = Math.min(len - off - written, input.src.capacity() - input.src.position());
|
||||||
input.src.put(arr, off, writeSize);
|
input.src.put(arr, off + written, writeSize);
|
||||||
if (input.src.position() == input.src.capacity()) flush();
|
if (input.src.position() == input.src.capacity()) flush();
|
||||||
written += writeSize;
|
written += writeSize;
|
||||||
}
|
}
|
||||||
|
@@ -15,11 +15,123 @@ import java.nio.file.Path;
|
|||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.security.DigestInputStream;
|
import java.security.DigestInputStream;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
|
import java.util.Random;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
class SplitOutputStream extends OutputStream {
|
||||||
|
private OutputStream[] sinks;
|
||||||
|
|
||||||
|
public SplitOutputStream(OutputStream... sinks) {
|
||||||
|
this.sinks = sinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(int i) throws IOException {
|
||||||
|
for (OutputStream os : sinks) {
|
||||||
|
os.write(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] b, int off, int len) throws IOException {
|
||||||
|
for (OutputStream os : sinks) {
|
||||||
|
os.write(b, off, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
for (OutputStream os : sinks) {
|
||||||
|
os.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HexSequenceGenerator extends InputStream {
|
||||||
|
private long count;
|
||||||
|
private long length;
|
||||||
|
|
||||||
|
private static char[] chars = "0123456789ABCDEF\n".toCharArray();
|
||||||
|
|
||||||
|
public HexSequenceGenerator(long length) {
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() {
|
||||||
|
int result;
|
||||||
|
if (count < length) {
|
||||||
|
result = chars[(int)(count % chars.length)];
|
||||||
|
++count;
|
||||||
|
} else result = -1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public int read(byte[] arr, int off, int len) {
|
||||||
|
if(count == length) return -1;
|
||||||
|
else {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < len && count + i < length; i++) {
|
||||||
|
arr[i] = (byte) chars[(int)((count + i) % chars.length)];
|
||||||
|
}
|
||||||
|
count += i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RandomBytesGenerator extends InputStream {
|
||||||
|
private Random random;
|
||||||
|
|
||||||
|
private long count;
|
||||||
|
private long length;
|
||||||
|
|
||||||
|
public RandomBytesGenerator(long seed, long length) {
|
||||||
|
this.random = new Random(seed);
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() {
|
||||||
|
int result;
|
||||||
|
if (count < length) {
|
||||||
|
result = (byte) random.nextInt();
|
||||||
|
++count;
|
||||||
|
} else result = -1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public int read(byte[] arr, int off, int len) {
|
||||||
|
if(count == length) return -1;
|
||||||
|
else {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < len && count + i < length; i++) {
|
||||||
|
arr[i] = (byte) random.nextInt();
|
||||||
|
}
|
||||||
|
count += i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class BasicTest {
|
public class BasicTest {
|
||||||
|
|
||||||
|
final private static char[] hexArray = "0123456789ABCDEF".toCharArray();
|
||||||
|
|
||||||
|
public static String bytesToHex(byte[] bytes) {
|
||||||
|
char[] hexChars = new char[bytes.length * 2];
|
||||||
|
for(int j = 0; j < bytes.length; j++) {
|
||||||
|
int v = bytes[j] & 0xFF;
|
||||||
|
hexChars[j * 2] = hexArray[v >>> 4];
|
||||||
|
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
|
||||||
|
}
|
||||||
|
return new String(hexChars);
|
||||||
|
}
|
||||||
|
|
||||||
private static class InputStreamProvider implements ArgumentsProvider {
|
private static class InputStreamProvider implements ArgumentsProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -27,7 +139,10 @@ public class BasicTest {
|
|||||||
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
|
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
Arguments.of(getClass().getResourceAsStream("/index.html")),
|
Arguments.of(getClass().getResourceAsStream("/index.html")),
|
||||||
Arguments.of(Files.newInputStream(Paths.get("/tmp/citylots.json")))
|
Arguments.of(new RandomBytesGenerator(123456, 1000)),
|
||||||
|
Arguments.of(new RandomBytesGenerator(654321, 65536)),
|
||||||
|
Arguments.of(new RandomBytesGenerator(101325, 12345678)),
|
||||||
|
Arguments.of(new HexSequenceGenerator(12345678))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,47 +152,51 @@ public class BasicTest {
|
|||||||
@ArgumentsSource(InputStreamProvider.class)
|
@ArgumentsSource(InputStreamProvider.class)
|
||||||
public void test(InputStream testStream) {
|
public void test(InputStream testStream) {
|
||||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||||
|
boolean debug = false;
|
||||||
|
|
||||||
|
int compressedSize;
|
||||||
ByteArrayInputStream compressedStream;
|
ByteArrayInputStream compressedStream;
|
||||||
try (InputStream is = new DigestInputStream(new BufferedInputStream(testStream), md5)) {
|
try (InputStream is = new DigestInputStream(new BufferedInputStream(testStream), md5)) {
|
||||||
|
OutputStream os;
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
try (OutputStream os = ZstdOutputStream.from(baos)) {
|
os = baos;
|
||||||
byte[] buffer = new byte[0x1000];
|
if(debug) {
|
||||||
|
os = new SplitOutputStream(os, Files.newOutputStream(Paths.get("/tmp/out.bin.zst")));
|
||||||
|
}
|
||||||
|
os = ZstdOutputStream.from(os);
|
||||||
|
if (debug) {
|
||||||
|
new SplitOutputStream(
|
||||||
|
os,
|
||||||
|
Files.newOutputStream(Paths.get("/tmp/out.bin.original")));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
byte[] buffer = new byte[0x100000];
|
||||||
while (true) {
|
while (true) {
|
||||||
int read = is.read(buffer);
|
int read = is.read(buffer);
|
||||||
if (read < 0) break;
|
if (read < 0) break;
|
||||||
os.write(buffer, 0, read);
|
os.write(buffer, 0, read);
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
os.close();
|
||||||
}
|
}
|
||||||
compressedStream = new ByteArrayInputStream(baos.toByteArray());
|
byte[] compressedBytes = baos.toByteArray();
|
||||||
|
compressedSize = compressedBytes.length;
|
||||||
|
compressedStream = new ByteArrayInputStream(compressedBytes);
|
||||||
}
|
}
|
||||||
|
System.out.printf("Compressed size: %d\n", compressedSize);
|
||||||
final byte[] originalDigest = md5.digest();
|
final byte[] originalDigest = md5.digest();
|
||||||
md5.reset();
|
md5.reset();
|
||||||
try (InputStream is = new DigestInputStream(
|
try (InputStream is = new DigestInputStream(
|
||||||
ZstdInputStream.from(compressedStream), md5)) {
|
ZstdInputStream.from(compressedStream), md5)) {
|
||||||
byte [] buffer = new byte[0x100000];
|
byte[] buffer = new byte[0x10000];
|
||||||
while (true) {
|
while (true) {
|
||||||
int read = is.read(buffer);
|
int read = is.read(buffer);
|
||||||
if (read < 0) break;
|
if (read < 0) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
byte[] roundTripDigest = md5.digest();
|
byte[] roundTripDigest = md5.digest();
|
||||||
|
System.out.printf("Original digest: %s\n", bytesToHex(originalDigest));
|
||||||
|
System.out.printf("Round trip digest: %s\n", bytesToHex(roundTripDigest));
|
||||||
Assertions.assertArrayEquals(originalDigest, roundTripDigest);
|
Assertions.assertArrayEquals(originalDigest, roundTripDigest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
@Test
|
|
||||||
public void test2() {
|
|
||||||
Path inputFile = Paths.get("/tmp/Richard_Dawkins_The_Selfish_Gene.pdf");
|
|
||||||
try(InputStream is = Files.newInputStream(inputFile)) {
|
|
||||||
try(OutputStream os = ZstdOutputStream.from(Files.newOutputStream(Paths.get("/tmp/Richard_Dawkins_The_Selfish_Gene.pdf.zst")))) {
|
|
||||||
byte[] buffer = new byte[0x10000];
|
|
||||||
while(true) {
|
|
||||||
int read = is.read(buffer);
|
|
||||||
if(read < 0) break;
|
|
||||||
os.write(buffer, 0, read);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user