Refactored some stream classes and added PositionalInputStream
This commit is contained in:
parent
946f5f5133
commit
5771133792
7 changed files with 290 additions and 68 deletions
|
|
@ -25,38 +25,28 @@
|
||||||
package zutil.io;
|
package zutil.io;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
import java.io.FilterInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple Class that mirrors a InputStream but
|
* A simple Class that mirrors a InputStream but also has additional Closeable objects that
|
||||||
* also has an additional Closeable objects that
|
* will be closed at the same time as the {@link #close()} method is called.
|
||||||
* will be closed when the this object is closed.
|
|
||||||
*
|
*
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class InputStreamCloser extends InputStream{
|
public class InputStreamCloser extends FilterInputStream {
|
||||||
private Closeable[] c;
|
private Closeable[] additionalClosable;
|
||||||
private InputStream in;
|
|
||||||
|
|
||||||
public InputStreamCloser(InputStream in, Closeable... c) {
|
public InputStreamCloser(InputStream in, Closeable... additionalClosable) {
|
||||||
this.c = c;
|
super(in);
|
||||||
this.in = in;
|
this.additionalClosable = additionalClosable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
in.close();
|
super.close();
|
||||||
for (Closeable stream : c)
|
|
||||||
|
for (Closeable stream : additionalClosable)
|
||||||
stream.close();
|
stream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mirror functions
|
|
||||||
public int read() throws IOException { return in.read(); }
|
|
||||||
public int read(byte b[]) throws IOException { return in.read(b); }
|
|
||||||
public int read(byte b[], int off, int len) throws IOException { return in.read(b, off, len); }
|
|
||||||
public long skip(long n) throws IOException { return in.skip(n); }
|
|
||||||
public int available() throws IOException { return in.available(); }
|
|
||||||
public synchronized void mark(int readlimit) { in.mark(readlimit); }
|
|
||||||
public synchronized void reset() throws IOException { in.reset(); }
|
|
||||||
public boolean markSupported() { return in.markSupported(); }
|
|
||||||
}
|
}
|
||||||
82
src/zutil/io/PositionalInputStream.java
Normal file
82
src/zutil/io/PositionalInputStream.java
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
package zutil.io;
|
||||||
|
|
||||||
|
import java.io.FilterInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A InputStream wrapper that counts the current position in the data stream which equals the amount of data read.
|
||||||
|
*/
|
||||||
|
public class PositionalInputStream extends FilterInputStream {
|
||||||
|
|
||||||
|
private long pos = 0;
|
||||||
|
private long mark = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param in the underlying input stream.
|
||||||
|
*/
|
||||||
|
protected PositionalInputStream(InputStream in) {
|
||||||
|
super(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the current position in the data stream
|
||||||
|
*/
|
||||||
|
public synchronized long getPosition() {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
int b = super.read();
|
||||||
|
|
||||||
|
synchronized(this) {
|
||||||
|
if (b >= 0) pos += 1;
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte[] b, int off, int len) throws IOException {
|
||||||
|
int n = super.read(b, off, len);
|
||||||
|
|
||||||
|
synchronized(this) {
|
||||||
|
if (n > 0) pos += n;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long skip(long skip) throws IOException {
|
||||||
|
long n = super.skip(skip);
|
||||||
|
|
||||||
|
synchronized(this) {
|
||||||
|
if (n > 0) pos += n;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mark(int readlimit) {
|
||||||
|
super.mark(readlimit);
|
||||||
|
|
||||||
|
synchronized(this) {
|
||||||
|
mark = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void reset() throws IOException {
|
||||||
|
super.reset();
|
||||||
|
|
||||||
|
synchronized(this) {
|
||||||
|
// Only update the position if mark is supported,
|
||||||
|
// as reset succeeds even if mark is not supported.
|
||||||
|
if (markSupported())
|
||||||
|
pos = mark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -25,30 +25,30 @@
|
||||||
package zutil.io;
|
package zutil.io;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class saves all the input data in to an StringBuffer
|
* This InputStream uses a string as the data source.
|
||||||
*
|
*
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class StringInputStream extends InputStream{
|
public class StringInputStream extends InputStream {
|
||||||
// The buffer
|
|
||||||
protected StringBuilder buffer;
|
private StringBuilder buffer = new StringBuilder();
|
||||||
|
private int pos;
|
||||||
|
private int mark;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an new instance of this class
|
* Creates a new instance of this class
|
||||||
*/
|
*/
|
||||||
public StringInputStream() {
|
public StringInputStream() { }
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringInputStream(String data) {
|
public StringInputStream(String data) {
|
||||||
clear();
|
|
||||||
add(data);
|
add(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an estimate of the number of bytes
|
* Returns an estimate of the number of bytes
|
||||||
* that can be read (or skipped over) from this
|
* that can be read (or skipped over) from this
|
||||||
|
|
@ -56,44 +56,37 @@ public class StringInputStream extends InputStream{
|
||||||
* invocation of a method for this input stream.
|
* invocation of a method for this input stream.
|
||||||
*/
|
*/
|
||||||
public int available() {
|
public int available() {
|
||||||
return buffer.length();
|
return buffer.length() - pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the next byte of data from the input stream.
|
* Reads the next byte of data from the input stream.
|
||||||
*/
|
*/
|
||||||
public int read() {
|
public synchronized int read() {
|
||||||
if (buffer.length() == 0)
|
if (available() <= 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int ret = buffer.charAt(0);
|
int ret = buffer.charAt(pos);
|
||||||
buffer.deleteCharAt(0);
|
pos++;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads some number of bytes from the input stream
|
* Reads up to len bytes of data from the input stream into an array of bytes.
|
||||||
* and stores them into the buffer array b.
|
|
||||||
*/
|
*/
|
||||||
public int read(byte[] b) {
|
public synchronized int read(byte[] b, int off, int len) {
|
||||||
return read(b, 0, b.length);
|
if (available() <= 0)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads up to len bytes of data from the input stream
|
|
||||||
* into an array of bytes.
|
|
||||||
*/
|
|
||||||
public int read(byte[] b, int off, int len) {
|
|
||||||
if (buffer.length() == 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (buffer.length() < len) {
|
if (available() < len)
|
||||||
len = buffer.length();
|
len = available();
|
||||||
|
|
||||||
|
for (int i=0; i<len; i++) {
|
||||||
|
b[off + i] = (byte) buffer.charAt(pos);
|
||||||
|
pos++;
|
||||||
}
|
}
|
||||||
byte[] btmp = buffer.substring(0, len).getBytes(StandardCharsets.ISO_8859_1);
|
|
||||||
System.arraycopy(btmp, 0, b, off, len);
|
|
||||||
buffer.delete(0, len);
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,16 +97,12 @@ public class StringInputStream extends InputStream{
|
||||||
*
|
*
|
||||||
* @param n is the amount characters to skip
|
* @param n is the amount characters to skip
|
||||||
*/
|
*/
|
||||||
public long skip(long n) {
|
public synchronized long skip(long n) {
|
||||||
if (buffer.length() < n) {
|
if (available() < n)
|
||||||
int len = buffer.length();
|
n = available();
|
||||||
buffer.delete(0, len);
|
|
||||||
return len;
|
pos += n;
|
||||||
}
|
return n;
|
||||||
else {
|
|
||||||
buffer.delete(0, (int) n);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -121,7 +110,23 @@ public class StringInputStream extends InputStream{
|
||||||
* reset methods.
|
* reset methods.
|
||||||
*/
|
*/
|
||||||
public boolean markSupported() {
|
public boolean markSupported() {
|
||||||
return false;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current position as a sae point that can be returned to with the {@link #reset()} method
|
||||||
|
*
|
||||||
|
* @param readLimit parameter not used.
|
||||||
|
*/
|
||||||
|
public synchronized void mark(int readLimit) {
|
||||||
|
mark = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the reading position back to the mark point.
|
||||||
|
*/
|
||||||
|
public synchronized void reset() {
|
||||||
|
pos = mark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -133,8 +138,19 @@ public class StringInputStream extends InputStream{
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public synchronized void clear() {
|
||||||
buffer = new StringBuilder();
|
buffer = new StringBuilder();
|
||||||
|
pos = 0;
|
||||||
|
mark = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the part of the String buffer that has already been read.
|
||||||
|
*/
|
||||||
|
public synchronized void clearOld() {
|
||||||
|
buffer.delete(0, pos);
|
||||||
|
pos = 0;
|
||||||
|
mark = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(String data) {
|
public void add(String data) {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ package zutil.io;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class saves all the input data in to an StringBuffer
|
* This class saves all the input data into a String
|
||||||
*
|
*
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -45,12 +45,13 @@ public class FQDNStringSerializer implements BinaryFieldSerializer<String> {
|
||||||
str.append('.');
|
str.append('.');
|
||||||
|
|
||||||
if ((c & 0b1100_0000) == 0b1100_0000) {
|
if ((c & 0b1100_0000) == 0b1100_0000) {
|
||||||
// This a pointer
|
// This a offset pointer to the String data
|
||||||
int offset = (c & 0b0011_1111) << 8;
|
int offset = (c & 0b0011_1111) << 8;
|
||||||
offset |= in.read() & 0b1111_1111;
|
offset |= in.read() & 0b1111_1111;
|
||||||
str.append(offset);
|
str.append(offset);
|
||||||
|
break; // PTR is always the last part of the FQDN
|
||||||
} else {
|
} else {
|
||||||
// Normal String
|
// Normal String data
|
||||||
for (int i = 0; i < c; ++i) {
|
for (int i = 0; i < c; ++i) {
|
||||||
str.append((char) in.read());
|
str.append((char) in.read());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
75
test/zutil/io/PositionalInputStreamTest.java
Normal file
75
test/zutil/io/PositionalInputStreamTest.java
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
package zutil.io;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
|
||||||
|
public class PositionalInputStreamTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void read() throws IOException {
|
||||||
|
PositionalInputStream in = new PositionalInputStream(new StringInputStream("hello"));
|
||||||
|
|
||||||
|
assertEquals(0, in.getPosition());
|
||||||
|
assertEquals('h', (char) in.read());
|
||||||
|
assertEquals(1, in.getPosition());
|
||||||
|
assertEquals('e', (char) in.read());
|
||||||
|
assertEquals(2, in.getPosition());
|
||||||
|
assertEquals('l', (char) in.read());
|
||||||
|
assertEquals(3, in.getPosition());
|
||||||
|
assertEquals('l', (char) in.read());
|
||||||
|
assertEquals(4, in.getPosition());
|
||||||
|
assertEquals('o', (char) in.read());
|
||||||
|
assertEquals(5, in.getPosition());
|
||||||
|
assertEquals(-1, in.read());
|
||||||
|
assertEquals(5, in.getPosition());
|
||||||
|
assertEquals(-1, in.read());
|
||||||
|
assertEquals(5, in.getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void readArray() throws IOException {
|
||||||
|
PositionalInputStream in = new PositionalInputStream(new StringInputStream("hello world"));
|
||||||
|
|
||||||
|
byte[] buffer = new byte[20];
|
||||||
|
assertEquals(5, in.read(buffer, 0, 5));
|
||||||
|
assertEquals("hello", new String(buffer, 0, 5));
|
||||||
|
assertEquals(5, in.getPosition());
|
||||||
|
|
||||||
|
assertEquals(' ', (char) in.read());
|
||||||
|
assertEquals(6, in.getPosition());
|
||||||
|
|
||||||
|
assertEquals(5, in.read(buffer));
|
||||||
|
assertEquals("world", new String(buffer, 0, 5));
|
||||||
|
assertEquals(11, in.getPosition());
|
||||||
|
|
||||||
|
assertEquals(-1, in.read());
|
||||||
|
assertEquals(11, in.getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void skip() throws IOException {
|
||||||
|
PositionalInputStream in = new PositionalInputStream(new StringInputStream("hello world"));
|
||||||
|
|
||||||
|
assertEquals(5, in.skip(5));
|
||||||
|
assertEquals(5, in.getPosition());
|
||||||
|
assertEquals(6, in.skip(20));
|
||||||
|
assertEquals(11, in.getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mark() throws IOException {
|
||||||
|
PositionalInputStream in = new PositionalInputStream(new StringInputStream("hello world"));
|
||||||
|
|
||||||
|
in.mark(20);
|
||||||
|
assertEquals(6, in.skip(6));
|
||||||
|
assertEquals(6, in.getPosition());
|
||||||
|
in.reset();
|
||||||
|
assertEquals(0, in.getPosition());
|
||||||
|
assertEquals('h', (char) in.read());
|
||||||
|
assertEquals(1, in.getPosition());
|
||||||
|
}
|
||||||
|
}
|
||||||
58
test/zutil/io/StringInputStreamTest.java
Normal file
58
test/zutil/io/StringInputStreamTest.java
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
package zutil.io;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
|
||||||
|
public class StringInputStreamTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void read() throws IOException {
|
||||||
|
StringInputStream in = new StringInputStream("hello");
|
||||||
|
|
||||||
|
assertEquals('h', (char) in.read());
|
||||||
|
assertEquals('e', (char) in.read());
|
||||||
|
assertEquals('l', (char) in.read());
|
||||||
|
assertEquals('l', (char) in.read());
|
||||||
|
assertEquals('o', (char) in.read());
|
||||||
|
assertEquals(-1, in.read());
|
||||||
|
assertEquals(-1, in.read());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void readArray() throws IOException {
|
||||||
|
StringInputStream in = new StringInputStream("hello world");
|
||||||
|
|
||||||
|
byte[] buffer = new byte[20];
|
||||||
|
assertEquals(5, in.read(buffer, 0, 5));
|
||||||
|
assertEquals("hello", new String(buffer, 0, 5));
|
||||||
|
|
||||||
|
assertEquals(' ', (char) in.read());
|
||||||
|
|
||||||
|
assertEquals(5, in.read(buffer));
|
||||||
|
assertEquals("world", new String(buffer, 0, 5));
|
||||||
|
|
||||||
|
assertEquals(-1, in.read());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void skip() {
|
||||||
|
StringInputStream in = new StringInputStream("hello world");
|
||||||
|
|
||||||
|
assertEquals(5, in.skip(5));
|
||||||
|
assertEquals(6, in.skip(20));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mark() throws IOException {
|
||||||
|
StringInputStream in = new StringInputStream("hello world");
|
||||||
|
|
||||||
|
in.mark(20);
|
||||||
|
assertEquals(6, in.skip(6));
|
||||||
|
in.reset();
|
||||||
|
assertEquals('h', (char) in.read());
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue