com.github.powerlibraries.io.builder.InBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of iopower Show documentation
Show all versions of iopower Show documentation
Power Libraries is a small project to collect some repeatedly needed or otherwise useful Java 8 classes in a collection of tiny libraries.
IO Power is the first and really tiny library of the Power Libraries. It contains some simple helper method for opening Input- and Outputstreams. The main purpose of IO Power is to make opening streams, readers and writers less cluttered and simple to understand.
package com.github.powerlibraries.io.builder;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.stream.Stream;
import java.util.zip.InflaterInputStream;
import java.util.zip.ZipInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import com.github.powerlibraries.io.builder.sources.Source;
import com.github.powerlibraries.io.functions.InputStreamWrapper;
import com.github.powerlibraries.io.functions.ReaderWrapper;
import com.github.powerlibraries.io.helper.CompressorRegistry;
/**
* This builder is used to create an input chain.
*
* @author Manuel Hegner
*
*/
@SuppressWarnings("unchecked")
public class InBuilder extends CharsetHolder{
private Source source;
private boolean decompress=false;
private Base64.Decoder base64Decoder=null;
private InputStreamWrapper decompressionWrapper;
private List streamWrappers;
private List readerWrappers;
public InBuilder(Source source) {
this.source=source;
}
/**
* Adds a wrapper around the generated InputStream before creating a Writer or
* a special type of input. This wrapper will be applied before decompression.
* @param wrapper the wrapper to apply to the generated InputStream
* @return this builder
*/
public InBuilder wrap(InputStreamWrapper wrapper) {
if(streamWrappers==null)
streamWrappers=new ArrayList<>();
streamWrappers.add(wrapper);
return this;
}
/**
* Adds a wrapper around the generated Reader before creating a Reader or
* a special type of input. This wrapper will only be applied if the created
* input uses Readers.
* @param wrapper the wrapper to apply to the generated Reader
* @return this builder
*/
public InBuilder wrap(ReaderWrapper wrapper) {
if(readerWrappers==null)
readerWrappers=new ArrayList<>();
readerWrappers.add(wrapper);
return this;
}
/**
* This method will tell the builder to decompress the bytes. The returned reader or stream will contain an
* appropriate decompressor. If the defined source specifies a name with a file ending, the builder will try to
* use the appropriate decompressor for the file extension. If there is no extension or it is unknown this
* simply adds a {@link DeflaterInputStream} to the chain.
*
* If you want to add file extensions to the automatic selection see {@link CompressorRegistry#registerWrapper}.
* @return this builder
*/
public InBuilder decompress() {
decompress=true;
return this;
}
/**
* This method will tell the builder to decompress the bytes using the given compression, e.g. GZipInputStream::new
.
* @param wrapper the wrapper used to decompress the bytes
* @return this builder
*/
public InBuilder decompress(InputStreamWrapper wrapper) {
decompress=true;
decompressionWrapper=wrapper;
return this;
}
/**
* This method will add a {@link Base64.Decoder} to this chain.
* @return this builder
*/
public InBuilder decodeBase64() {
base64Decoder=Base64.getDecoder();
return this;
}
/**
* This method will add a {@link Base64.Decoder} to this chain.
* @param decoder the specific decoder that should be used.
* @return this builder
*/
public InBuilder decodeBase64(Base64.Decoder decoder) {
base64Decoder=decoder;
return this;
}
/**
* This method creates a simple {@link InputStream} from this builder with all the chosen options.
* @return an {@link InputStream}
* @throws IOException if any element of the chain throws an {@link IOException}
*/
public InputStream asStream() throws IOException {
return createInputStream();
}
/**
* This method creates a {@link BufferedReader} from this builder with all the chosen options. It uses the default
* {@link Charset} for that.
* @return a {@link BufferedReader}
* @throws IOException if any element of the chain throws an {@link IOException}
*/
public BufferedReader asReader() throws IOException {
return new BufferedReader(new InputStreamReader(createInputStream(), getCharset()));
}
/**
* This method creates an {@link ObjectInputStream} from this builder with all the chosen options.
* @return a {@link ObjectInputStream}
* @throws IOException if any element of the chain throws an {@link IOException}
*/
public ObjectInputStream asObjects() throws IOException {
return new ObjectInputStream(new BufferedInputStream(createInputStream()));
}
/**
* This method creates an {@link DataInputStream} from this builder with all the chosen options.
* @return a {@link DataInputStream}
* @throws IOException if any element of the chain throws an {@link IOException}
*/
public DataInputStream asData() throws IOException {
return new DataInputStream(new BufferedInputStream(createInputStream()));
}
/**
* This method creates an {@link ZipInputStream} from this builder with all the chosen options.
* @return a {@link ZipInputStream}
* @throws IOException if any element of the chain throws an {@link IOException}
*/
public ZipInputStream asZip() throws IOException {
return new ZipInputStream(new BufferedInputStream(createInputStream()));
}
/**
* This method reads an XML document from the selected source into a {@link Document}.
* It uses a default {@link DocumentBuilderFactory} and {@link DocumentBuilder}.
* @return the parsed Document
* @throws IOException if any element of the chain throws an {@link IOException}
* @throws SAXException if any parse errors occur
*/
public Document readXML() throws IOException, SAXException {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
return readXML(builder);
} catch (ParserConfigurationException e) {
throw new RuntimeException("DocumentBuilder creation failed", e);
}
}
/**
* This method reads an XML document from the selected source into a {@link Document}.
* @param documentBuilder a fresh {@link DocumentBuilder} that is used as parser
* @return the parsed Document
* @throws IOException if any element of the chain throws an {@link IOException}
* @throws SAXException if any parse errors occur
*/
public Document readXML(DocumentBuilder documentBuilder) throws IOException, SAXException {
try(BufferedInputStream in=new BufferedInputStream(this.asStream())) {
return documentBuilder.parse(in);
}
}
/**
* This method reads the complete input in a String. Lines are seperated with a single '\n'.
* @return a String containing the whole content of the file
* @throws IOException if any element of the chain throws an {@link IOException}
*/
public String readAll() throws IOException {
try(BufferedReader in=this.asReader()) {
StringBuilder sb=new StringBuilder();
String l;
while((l=in.readLine())!=null) {
sb.append(l).append('\n');
}
if(sb.length()==0)
return "";
else
return sb.substring(0, sb.length()-1);
}
}
/**
* This method simply reads the first object from the input using an
* {@link ObjectInputStream} and returns it.
* @param the expected type of the read object
* @return the read Object
* @throws ClassNotFoundException if the class of a serialized object cannot be found.
* @throws IOException if any element of the chain throws an {@link IOException}
*/
public T readObject() throws ClassNotFoundException, IOException {
try(ObjectInputStream in=this.asObjects()) {
return (T)in.readObject();
}
}
/**
* This method reads as many objects from the input using an
* {@link ObjectInputStream} as it can and returns them. Be aware that
* this method will throw an exception if there are other information in the stream
* than objects (e.g. primitives).
* @param the expected supertype of the read objects
* @return a list of read objects
* @throws ClassNotFoundException if the class of a serialized object cannot be found.
* @throws IOException if any element of the chain throws an {@link IOException}
*/
public List readObjects() throws ClassNotFoundException, IOException {
try(ObjectInputStream in=this.asObjects()) {
ArrayList objects=new ArrayList<>();
while(in.available()>0) {
try {
objects.add((T)in.readObject());
} catch(ClassNotFoundException e) {
throw new ClassNotFoundException("Error while trying to deserialize object "+objects.size(), e);
} catch(IOException e) {
throw new IOException("Error while trying to deserialize object "+objects.size(), e);
}
}
return objects;
}
}
/**
* This method reads the complete input in a {@link List} of Strings. Each element of the list
* represents one line of the source document.
* @return a list of lines containing the whole content of the file
* @throws IOException if any element of the chain throws an {@link IOException}
*/
public List readLines() throws IOException {
try(BufferedReader in=this.asReader()) {
ArrayList list=new ArrayList<>();
String l;
while((l=in.readLine())!=null)
list.add(l);
return list;
}
}
/**
* This method reads to the given array from offset to offset+length from the defined {@link InputStream} and closes it.
* @param bytes the byte array to write
* @param offset the offset in the byte array
* @param length the length of the bytes to read
* @throws IOException if any element of the chain throws an {@link IOException}
*/
public void readBytes(byte[] bytes, int offset, int length) throws IOException {
try(InputStream in = this.asStream()) {
in.read(bytes, offset, length);
}
}
/**
* This method reads to the given array completely from the {@link InputStream} and closes it.
* @param bytes the byte array to read
* @throws IOException if any element of the chain throws an {@link IOException}
*/
public void readBytes(byte[] bytes) throws IOException {
readBytes(bytes, 0, bytes.length);
}
/**
* This method reads the given number of bytes from the defined {@link InputStream}, closes it, and returns the read bytes.
* @param length the number of bytes to read
* @throws IOException if any element of the chain throws an {@link IOException}
*/
public byte[] readBytes(int length) throws IOException {
byte[] bytes = new byte[length];
readBytes(bytes);
return bytes;
}
/**
* Copies the content of this {@link InputStream} to the given {@link OutputStream}.
* This does not close the {@link OutputStream}.
* @param out the {@link OutputStream} to copy to
* @throws IOException if any element of the chain throws an {@link IOException}
*/
public void copyTo(OutputStream out) throws IOException {
try(InputStream in=createInputStream()) {
byte[] buffer = new byte[8192];
int len = 0;
while ((len=in.read(buffer)) != -1)
out.write(buffer, 0, len);
}
}
/**
* Copies the content of this {@link BufferedReader} to the given {@link Writer}.
* This does not close the {@link Writer}.
* @param out the {@link Writer} to copy to
* @throws IOException if any element of the chain throws an {@link IOException}
*/
public void copyTo(Writer out) throws IOException {
try(BufferedReader in=this.asReader()) {
char[] buffer = new char[4096];
int len = 0;
while ((len=in.read(buffer)) != -1)
out.write(buffer, 0, len);
}
}
/**
* This method reads the complete input in a {@link Stream} of Strings. Each element of the stream
* represents one line of the source document. The stream is lazily populated. Be aware that the created
* reader is only closed if the created stream is closed.
* @return a {@link Stream} containing the lines of this input
* @throws IOException if any element of the chain throws an {@link IOException}
*/
public Stream streamLines() throws IOException {
BufferedReader in=this.asReader();
return in.lines().onClose(() -> {
try {
in.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
private InputStream createInputStream() throws IOException {
InputStream stream=source.openStream();
if(decompress) {
if(decompressionWrapper!=null)
stream=decompressionWrapper.wrap(stream);
else if(source.hasName() && CompressorRegistry.getInstance().canWrapInput(source.getName()))
stream=CompressorRegistry.getInstance().wrap(source.getName(), stream);
else
stream=new InflaterInputStream(stream);
}
if(base64Decoder!=null)
stream=base64Decoder.wrap(stream);
return stream;
}
/**
* @return the source used by this InBuilder
*/
public Source getSource() {
return source;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy