X-Git-Url: http://git.nikiroo.be/?p=fanfix.git;a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Futils%2Fstreams%2FReplaceOutputStream.java;fp=src%2Fbe%2Fnikiroo%2Futils%2Fstreams%2FReplaceOutputStream.java;h=c6679cc3b3eef4ad15e50e022013663c3b75dade;hp=0000000000000000000000000000000000000000;hb=d46b7b96f94e88a776bcd2dfd756549ffb300cc9;hpb=c9994f27667bc421bcd448d39e55774fddf5c431 diff --git a/src/be/nikiroo/utils/streams/ReplaceOutputStream.java b/src/be/nikiroo/utils/streams/ReplaceOutputStream.java new file mode 100644 index 0000000..c6679cc --- /dev/null +++ b/src/be/nikiroo/utils/streams/ReplaceOutputStream.java @@ -0,0 +1,148 @@ +package be.nikiroo.utils.streams; + +import java.io.IOException; +import java.io.OutputStream; + +import be.nikiroo.utils.StringUtils; + +/** + * This {@link OutputStream} will change some of its content by replacing it + * with something else. + * + * @author niki + */ +public class ReplaceOutputStream extends BufferedOutputStream { + private byte[][] froms; + private byte[][] tos; + + /** + * Create a {@link ReplaceOutputStream} that will replace from with + * to. + * + * @param out + * the under-laying {@link OutputStream} + * @param from + * the {@link String} to replace + * @param to + * the {@link String} to replace with + */ + public ReplaceOutputStream(OutputStream out, String from, String to) { + this(out, StringUtils.getBytes(from), StringUtils.getBytes(to)); + } + + /** + * Create a {@link ReplaceOutputStream} that will replace from with + * to. + * + * @param out + * the under-laying {@link OutputStream} + * @param from + * the value to replace + * @param to + * the value to replace with + */ + public ReplaceOutputStream(OutputStream out, byte[] from, byte[] to) { + this(out, new byte[][] { from }, new byte[][] { to }); + } + + /** + * Create a {@link ReplaceOutputStream} that will replace all froms + * with tos. + *

+ * Note that they will be replaced in order, and that for each from + * a to must correspond. + * + * @param out + * the under-laying {@link OutputStream} + * @param froms + * the values to replace + * @param tos + * the values to replace with + */ + public ReplaceOutputStream(OutputStream out, String[] froms, String[] tos) { + this(out, StreamUtils.getBytes(froms), StreamUtils.getBytes(tos)); + } + + /** + * Create a {@link ReplaceOutputStream} that will replace all froms + * with tos. + *

+ * Note that they will be replaced in order, and that for each from + * a to must correspond. + * + * @param out + * the under-laying {@link OutputStream} + * @param froms + * the values to replace + * @param tos + * the values to replace with + */ + public ReplaceOutputStream(OutputStream out, byte[][] froms, byte[][] tos) { + super(out); + bypassFlush = false; + + if (froms.length != tos.length) { + throw new IllegalArgumentException( + "For replacing, each FROM must have a corresponding TO"); + } + + this.froms = froms; + this.tos = tos; + } + + /** + * Flush the {@link BufferedOutputStream}, write the current buffered data + * to (and optionally also flush) the under-laying stream. + *

+ * If {@link BufferedOutputStream#bypassFlush} is false, all writes to the + * under-laying stream are done in this method. + *

+ * This can be used if you want to write some data in the under-laying + * stream yourself (in that case, flush this {@link BufferedOutputStream} + * with or without flushing the under-laying stream, then you can write to + * the under-laying stream). + *

+ * But be careful! If a replacement could be done with the end o the + * currently buffered data and the start of the data to come, we obviously + * will not be able to do it. + * + * @param includingSubStream + * also flush the under-laying stream + * @throws IOException + * in case of I/O error + */ + @Override + public void flush(boolean includingSubStream) throws IOException { + // Note: very simple, not efficient implementation; sorry. + while (start < stop) { + boolean replaced = false; + for (int i = 0; i < froms.length; i++) { + if (froms[i] != null + && froms[i].length > 0 + && StreamUtils + .startsWith(froms[i], buffer, start, stop)) { + if (tos[i] != null && tos[i].length > 0) { + out.write(tos[i]); + bytesWritten += tos[i].length; + } + + start += froms[i].length; + replaced = true; + break; + } + } + + if (!replaced) { + out.write(buffer[start++]); + bytesWritten++; + } + } + + start = 0; + stop = 0; + + if (includingSubStream) { + out.flush(); + } + } +}