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;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* A simple Class that mirrors a InputStream but
|
||||
* also has an additional Closeable objects that
|
||||
* will be closed when the this object is closed.
|
||||
* A simple Class that mirrors a InputStream but also has additional Closeable objects that
|
||||
* will be closed at the same time as the {@link #close()} method is called.
|
||||
*
|
||||
* @author Ziver
|
||||
*/
|
||||
public class InputStreamCloser extends InputStream{
|
||||
private Closeable[] c;
|
||||
private InputStream in;
|
||||
public class InputStreamCloser extends FilterInputStream {
|
||||
private Closeable[] additionalClosable;
|
||||
|
||||
public InputStreamCloser(InputStream in, Closeable... c) {
|
||||
this.c = c;
|
||||
this.in = in;
|
||||
public InputStreamCloser(InputStream in, Closeable... additionalClosable) {
|
||||
super(in);
|
||||
this.additionalClosable = additionalClosable;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
in.close();
|
||||
for (Closeable stream : c)
|
||||
super.close();
|
||||
|
||||
for (Closeable stream : additionalClosable)
|
||||
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;
|
||||
|
||||
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
|
||||
*
|
||||
*/
|
||||
public class StringInputStream extends InputStream{
|
||||
// The buffer
|
||||
protected StringBuilder buffer;
|
||||
public class StringInputStream extends InputStream {
|
||||
|
||||
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() {
|
||||
clear();
|
||||
}
|
||||
public StringInputStream() { }
|
||||
|
||||
public StringInputStream(String data) {
|
||||
clear();
|
||||
add(data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an estimate of the number of bytes
|
||||
* 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.
|
||||
*/
|
||||
public int available() {
|
||||
return buffer.length();
|
||||
return buffer.length() - pos;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads the next byte of data from the input stream.
|
||||
*/
|
||||
public int read() {
|
||||
if (buffer.length() == 0)
|
||||
public synchronized int read() {
|
||||
if (available() <= 0)
|
||||
return -1;
|
||||
|
||||
int ret = buffer.charAt(0);
|
||||
buffer.deleteCharAt(0);
|
||||
int ret = buffer.charAt(pos);
|
||||
pos++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads some number of bytes from the input stream
|
||||
* and stores them into the buffer array b.
|
||||
* Reads up to len bytes of data from the input stream into an array of bytes.
|
||||
*/
|
||||
public int read(byte[] b) {
|
||||
return read(b, 0, b.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
public synchronized int read(byte[] b, int off, int len) {
|
||||
if (available() <= 0)
|
||||
return -1;
|
||||
|
||||
if (buffer.length() < len) {
|
||||
len = buffer.length();
|
||||
if (available() < len)
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -104,16 +97,12 @@ public class StringInputStream extends InputStream{
|
|||
*
|
||||
* @param n is the amount characters to skip
|
||||
*/
|
||||
public long skip(long n) {
|
||||
if (buffer.length() < n) {
|
||||
int len = buffer.length();
|
||||
buffer.delete(0, len);
|
||||
return len;
|
||||
}
|
||||
else {
|
||||
buffer.delete(0, (int) n);
|
||||
return n;
|
||||
}
|
||||
public synchronized long skip(long n) {
|
||||
if (available() < n)
|
||||
n = available();
|
||||
|
||||
pos += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -121,7 +110,23 @@ public class StringInputStream extends InputStream{
|
|||
* reset methods.
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
public synchronized void clear() {
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ package zutil.io;
|
|||
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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -45,12 +45,13 @@ public class FQDNStringSerializer implements BinaryFieldSerializer<String> {
|
|||
str.append('.');
|
||||
|
||||
if ((c & 0b1100_0000) == 0b1100_0000) {
|
||||
// This a pointer
|
||||
// This a offset pointer to the String data
|
||||
int offset = (c & 0b0011_1111) << 8;
|
||||
offset |= in.read() & 0b1111_1111;
|
||||
str.append(offset);
|
||||
break; // PTR is always the last part of the FQDN
|
||||
} else {
|
||||
// Normal String
|
||||
// Normal String data
|
||||
for (int i = 0; i < c; ++i) {
|
||||
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