All Downloads are FREE. Search and download functionalities are using the official Maven repository.

shz.core.IOHelp Maven / Gradle / Ivy

There is a newer version: 10.3.1
Show newest version
package shz.core;

import shz.core.cl.ClassLoaderHelp;
import shz.core.model.tag.zxx.ZBTag;
import shz.core.model.tag.zxx.ZCTag;
import shz.core.model.tag.zxx.ZLTag;
import shz.core.msg.ClientFailureMsg;

import java.io.*;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.*;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public final class IOHelp {
    private IOHelp() {
        throw new IllegalStateException();
    }

    public static void flush(Flushable flushable) {
        if (flushable != null) try {
            flushable.flush();
        } catch (IOException ignored) {
        }
    }

    public static void flush(Flushable f1, Flushable f2) {
        flush(f1);
        flush(f2);
    }

    public static void close(AutoCloseable autoCloseable) {
        if (autoCloseable != null) try {
            autoCloseable.close();
        } catch (Exception ignored) {
        }
    }

    public static void close(AutoCloseable a1, AutoCloseable a2) {
        close(a1);
        close(a2);
    }

    public static void close(AutoCloseable a1, AutoCloseable a2, AutoCloseable a3) {
        close(a1);
        close(a2);
        close(a3);
    }

    public static InputStream getIsFromURL(URL url, String path, int dataSize) {
        url = url == null ? ClassLoaderHelp.get().getResource("") : url;
        if (url == null) return null;
        String protocol = url.getProtocol();
        try {
            URLConnection conn = url.openConnection();
            if ("file".equals(protocol)) {
                File file = FileHelp.fromUrl(conn.getURL());
                if (file.isFile()) {
                    if (FileHelp.equalsPath(file, path)) return getBis(file);
                    return null;
                }
                file = new File(file, path);
                if (file.exists() && file.isFile() && file.canRead()) return getBis(file);
                return getBis(FileHelp.findFile(path, Collections.singletonList(file.getAbsolutePath()), null));
            }
            if ("jar".equals(protocol)) {
                JarFile jarFile = ((JarURLConnection) conn).getJarFile();
                return getBis(ZipHelp.getIsFromJarFile(jarFile, path, dataSize));
            }
            return getBis(conn.getInputStream());
        } catch (IOException e) {
            throw PRException.of(e);
        }
    }

    public static InputStream getIsFromURL(URL url, String path) {
        return getIsFromURL(url, path, DEFAULT_DATA_SIZE);
    }

    public static InputStream getIsFromURL(String path) {
        return getIsFromURL(null, path);
    }

    public static final int DEFAULT_BUFFER_SIZE = 8192;
    public static final int DEFAULT_DATA_SIZE = 1024;

    public static BufferedInputStream getBis(InputStream is, int size) {
        return new BufferedInputStream(is, size);
    }

    public static BufferedInputStream getBis(InputStream is) {
        return getBis(is, DEFAULT_BUFFER_SIZE);
    }

    public static BufferedInputStream getBis(File file, int size) {
        return getBis(getFis(file), size);
    }

    private static FileInputStream getFis(File file) {
        try {
            return new FileInputStream(file);
        } catch (FileNotFoundException e) {
            throw PRException.of(e);
        }
    }

    public static BufferedInputStream getBis(File file) {
        return getBis(getFis(file), DEFAULT_BUFFER_SIZE);
    }

    public static BufferedInputStream getBis(String path, int size) {
        return getBis(getFis(new File(path)), size);
    }

    public static BufferedInputStream getBis(String path) {
        return getBis(getFis(new File(path)), DEFAULT_BUFFER_SIZE);
    }

    public static BufferedOutputStream getBos(OutputStream os, int size) {
        return new BufferedOutputStream(os, size);
    }

    public static BufferedOutputStream getBos(OutputStream os) {
        return getBos(os, DEFAULT_BUFFER_SIZE);
    }

    public static BufferedOutputStream getBos(File file, boolean append, int size) {
        return getBos(getFos(file, append), size);
    }

    private static FileOutputStream getFos(File file, boolean append) {
        try {
            return new FileOutputStream(file, append);
        } catch (FileNotFoundException e) {
            throw PRException.of(e);
        }
    }

    public static BufferedOutputStream getBos(File file) {
        return getBos(getFos(file, false), DEFAULT_BUFFER_SIZE);
    }

    public static BufferedOutputStream getBos(String path, boolean append, int size) {
        return getBos(getFos(path, append), size);
    }

    private static FileOutputStream getFos(String path, boolean append) {
        try {
            return new FileOutputStream(path, append);
        } catch (FileNotFoundException e) {
            throw PRException.of(e);
        }
    }

    public static BufferedOutputStream getBos(String path) {
        return getBos(getFos(path, false), DEFAULT_BUFFER_SIZE);
    }

    public static BufferedReader getBr(InputStream is, Charset charset, int size) {
        return new BufferedReader(new InputStreamReader(is, charset), size);
    }

    public static BufferedReader getBr(InputStream is, Charset charset) {
        return getBr(is, charset, DEFAULT_BUFFER_SIZE);
    }

    public static BufferedReader getBr(InputStream is) {
        return getBr(is, StandardCharsets.UTF_8, DEFAULT_BUFFER_SIZE);
    }

    public static BufferedReader getBr(Reader reader, int size) {
        return new BufferedReader(reader, size);
    }

    public static BufferedReader getBr(Reader reader) {
        return getBr(reader, DEFAULT_BUFFER_SIZE);
    }

    public static BufferedReader getBr(File file, int size) {
        return getBr(getFr(file), size);
    }

    private static FileReader getFr(File file) {
        try {
            return new FileReader(file);
        } catch (FileNotFoundException e) {
            throw PRException.of(e);
        }
    }

    public static BufferedReader getBr(File file) {
        return getBr(getFr(file), DEFAULT_BUFFER_SIZE);
    }

    public static BufferedReader getBr(String path, int size) {
        return getBr(getFr(new File(path)), size);
    }

    public static BufferedReader getBr(String path) {
        return getBr(getFr(new File(path)), DEFAULT_BUFFER_SIZE);
    }

    public static BufferedWriter getBw(OutputStream os, Charset charset, int size) {
        return new BufferedWriter(new OutputStreamWriter(os, charset), size);
    }

    public static BufferedWriter getBw(OutputStream os, Charset charset) {
        return getBw(os, charset, DEFAULT_BUFFER_SIZE);
    }

    public static BufferedWriter getBw(OutputStream os) {
        return getBw(os, StandardCharsets.UTF_8, DEFAULT_BUFFER_SIZE);
    }

    public static BufferedWriter getBw(Writer writer, int size) {
        return new BufferedWriter(writer, size);
    }

    public static BufferedWriter getBw(Writer writer) {
        return getBw(writer, DEFAULT_BUFFER_SIZE);
    }

    public static BufferedWriter getBw(File file, boolean append, int size) {
        return getBw(getFw(file, append), size);
    }

    private static FileWriter getFw(File file, boolean append) {
        try {
            return new FileWriter(file, append);
        } catch (IOException e) {
            throw PRException.of(e);
        }
    }

    public static BufferedWriter getBw(File file) {
        return getBw(getFw(file, false), DEFAULT_BUFFER_SIZE);
    }

    public static BufferedWriter getBw(String path, boolean append, int size) {
        return getBw(getFw(path, append), size);
    }

    private static FileWriter getFw(String path, boolean append) {
        try {
            return new FileWriter(path, append);
        } catch (IOException e) {
            throw PRException.of(e);
        }
    }

    public static BufferedWriter getBw(String path) {
        return getBw(getFw(path, false), DEFAULT_BUFFER_SIZE);
    }

    public static ZipInputStream getZis(InputStream is, Charset charset) {
        return new ZipInputStream(is, charset);
    }

    public static ZipInputStream getZis(InputStream is) {
        return getZis(is, StandardCharsets.UTF_8);
    }

    public static ZipInputStream getZis(File file, Charset charset) {
        return getZis(getFis(file), charset);
    }

    public static ZipInputStream getZis(File file) {
        return getZis(getFis(file), StandardCharsets.UTF_8);
    }

    public static ZipInputStream getZis(String path, Charset charset) {
        return getZis(getFis(new File(path)), charset);
    }

    public static ZipInputStream getZis(String path) {
        return getZis(getFis(new File(path)), StandardCharsets.UTF_8);
    }

    public static ZipOutputStream getZos(OutputStream os, Charset charset) {
        return new ZipOutputStream(os, charset);
    }

    public static ZipOutputStream getZos(OutputStream os) {
        return getZos(os, StandardCharsets.UTF_8);
    }

    public static ZipOutputStream getZos(File file, boolean append, Charset charset) {
        return getZos(getFos(file, append), charset);
    }

    public static ZipOutputStream getZos(File file) {
        return getZos(getFos(file, false), StandardCharsets.UTF_8);
    }

    public static ZipOutputStream getZos(String path, boolean append, Charset charset) {
        return getZos(getFos(path, append), charset);
    }

    public static ZipOutputStream getZos(String path) {
        return getZos(getFos(path, false), StandardCharsets.UTF_8);
    }

    public static JarInputStream getJis(InputStream is, boolean verify) {
        try {
            return new JarInputStream(is, verify);
        } catch (IOException e) {
            throw PRException.of(e);
        }
    }

    public static JarInputStream getJis(InputStream is) {
        return getJis(is, true);
    }

    public static JarInputStream getJis(File file, boolean verify) {
        return getJis(getFis(file), verify);
    }

    public static JarInputStream getJis(File file) {
        return getJis(getFis(file), true);
    }

    public static JarInputStream getJis(String path, boolean verify) {
        return getJis(getFis(new File(path)), verify);
    }

    public static JarInputStream getJis(String path) {
        return getJis(getFis(new File(path)), true);
    }

    public static JarOutputStream getJos(OutputStream os, Manifest man) {
        try {
            return man != null ? new JarOutputStream(os, man) : new JarOutputStream(os);
        } catch (IOException e) {
            throw PRException.of(e);
        }
    }

    public static JarOutputStream getJos(OutputStream os) {
        return getJos(os, null);
    }

    public static JarOutputStream getJos(File file, boolean append, Manifest man) {
        return getJos(getFos(file, append), man);
    }

    public static JarOutputStream getJos(File file) {
        return getJos(getFos(file, false), null);
    }

    public static JarOutputStream getJos(String path, boolean append, Manifest man) {
        return getJos(getFos(path, append), man);
    }

    public static JarOutputStream getJos(String path) {
        return getJos(getFos(path, false), null);
    }

    public static  long read(I i, long offset, long size, O o, int dataSize, Consumer update, BiConsumer f) {
        offset = Math.max(offset, 0L);
        int len = 0;
        try {
            if (offset > 0L) {
                long skip = i.skip(offset);
                if (skip <= offset) return 0L;
            }
            byte[] buffer = new byte[dataSize];
            if (size > 0L) {
                long n = size / dataSize;
                while (n-- > 0L && (len = i.read(buffer)) != -1) {
                    if (update == null) o.write(buffer, 0, len);
                    else if (o == null) update.accept(buffer);
                    else {
                        update.accept(buffer);
                        o.write(buffer, 0, len);
                    }
                    offset += len;
                }
                if (len >= 0 && (len = Math.min(i.read(buffer), (int) (size % dataSize))) != -1) {
                    if (update == null) o.write(buffer, 0, len);
                    else if (o == null) update.accept(buffer);
                    else {
                        update.accept(buffer);
                        o.write(buffer, 0, len);
                    }
                    offset += len;
                }
            } else {
                while ((len = i.read(buffer)) != -1) {
                    if (update == null) o.write(buffer, 0, len);
                    else if (o == null) update.accept(buffer);
                    else {
                        update.accept(buffer);
                        o.write(buffer, 0, len);
                    }
                    offset += len;
                }
            }
            flush(o);
        } catch (Exception e) {
            return offset == 0L ? -1L : offset;
        } finally {
            try {
                if (f == null) close(o, i);
                else f.accept(i, o);
            } catch (Throwable ignored) {
            }
        }
        return 0L;
    }

    public static  long read(I i, O o, int dataSize, Consumer update, BiConsumer f) {
        return read(i, 0L, 0L, o, dataSize, update, f);
    }

    public static  long read(I i, O o) {
        return read(i, o, DEFAULT_DATA_SIZE, null, null);
    }

    public static  void read(R r, W w, int dataSize, Consumer update, BiConsumer f) {
        int len;
        try {
            char[] buffer = new char[dataSize];
            while ((len = r.read(buffer)) != -1) {
                if (update == null) w.write(buffer, 0, len);
                else if (w == null) update.accept(buffer);
                else {
                    update.accept(buffer);
                    w.write(buffer, 0, len);
                }
            }
            flush(w);
        } catch (Exception e) {
            throw PRException.of(e);
        } finally {
            try {
                if (f == null) close(w, r);
                else f.accept(r, w);
            } catch (Throwable ignored) {
            }
        }
    }

    public static  void read(R reader, W writer) {
        read(reader, writer, DEFAULT_DATA_SIZE, null, null);
    }

    public static 
void read(BR br, BW bw, Function update, BiConsumer f) { String line; try { while ((line = br.readLine()) != null) { if (update == null) { bw.write(line); bw.newLine(); } else if (bw == null) update.apply(line); else { bw.write(update.apply(line)); bw.newLine(); } } flush(bw); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(bw, br); else f.accept(br, bw); } catch (Throwable ignored) { } } } public static
void read(BR br, BW bw) { read(br, bw, (Function) null, null); } public static
void read(BR br, BW bw, BiConsumer update, BiConsumer f) { String line; try { while ((line = br.readLine()) != null) update.accept(line, bw); flush(bw); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(bw, br); else f.accept(br, bw); } catch (Throwable ignored) { } } } public static
void read(BR br, BW bw, BiConsumer update) { read(br, bw, update, null); } public static
void read(BR br, BW bw, BiPredicate update, BiConsumer f) { String line; try { while ((line = br.readLine()) != null) if (update.test(line, bw)) break; flush(bw); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(bw, br); else f.accept(br, bw); } catch (Throwable ignored) { } } } public static
void read(BR br, BW bw, BiPredicate update) { read(br, bw, update, null); } public static long read(I i, long offset, long size, BiConsumer consumer, int dataSize, Consumer f) { offset = Math.max(offset, 0L); int len = 0; try { if (offset > 0L) { long skip = i.skip(offset); if (skip <= offset) return 0L; } byte[] buffer = new byte[dataSize]; if (size > 0L) { long n = size / dataSize; while (n-- > 0L && (len = i.read(buffer)) != -1) { consumer.accept(buffer, len); offset += len; } if (len >= 0 && (len = Math.min(i.read(buffer), (int) (size % dataSize))) != -1) { consumer.accept(buffer, len); offset += len; } } else while ((len = i.read(buffer)) != -1) { consumer.accept(buffer, len); offset += len; } } catch (Exception e) { return offset == 0L ? -1L : offset; } finally { try { if (f == null) close(i); else f.accept(i); } catch (Throwable ignored) { } } return 0L; } public static void read(I i, BiConsumer consumer, int dataSize, Consumer f) { read(i, 0L, 0L, consumer, dataSize, f); } public static void read(I i, BiConsumer consumer) { read(i, consumer, DEFAULT_DATA_SIZE, null); } public static void read(R r, BiConsumer consumer, int dataSize, Consumer f) { int len; try { char[] buffer = new char[dataSize]; while ((len = r.read(buffer)) != -1) consumer.accept(buffer, len); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(r); else f.accept(r); } catch (Throwable ignored) { } } } public static void read(R r, BiConsumer consumer) { read(r, consumer, DEFAULT_DATA_SIZE, null); } public static void read(R r, BiPredicate consumer, int dataSize, Consumer f) { int len; try { char[] buffer = new char[dataSize]; while ((len = r.read(buffer)) != -1) if (consumer.test(buffer, len)) break; } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(r); else f.accept(r); } catch (Throwable ignored) { } } } public static void read(R r, BiPredicate consumer) { read(r, consumer, DEFAULT_DATA_SIZE, null); } public static
void read(BR br, Consumer consumer, Consumer
f) { String line; try { while ((line = br.readLine()) != null) consumer.accept(line); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(br); else f.accept(br); } catch (Throwable ignored) { } } } public static
void read(BR br, Consumer consumer) { read(br, consumer, null); } public static
void read(BR br, Predicate consumer, Consumer
f) { String line; try { while ((line = br.readLine()) != null) if (consumer.test(line)) break; } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(br); else f.accept(br); } catch (Throwable ignored) { } } } public static
void read(BR br, Predicate consumer) { read(br, consumer, null); } public static long read(I i, long offset, long size, int dataSize, Collection bytes, Consumer f) { return read(i, offset, size, (buffer, len) -> { if (len == 0) return; byte[] des = new byte[len]; System.arraycopy(buffer, 0, des, 0, len); bytes.add(des); }, dataSize, f); } public static void read(I i, int dataSize, Collection bytes, Consumer f) { read(i, 0L, 0L, dataSize, bytes, f); } public static void read(I i, Collection bytes) { read(i, DEFAULT_DATA_SIZE, bytes, null); } public static long read(I i, long offset, long size, int dataSize, byte[] data, int dataOffset, Consumer f) { int available; try { available = i.available(); } catch (IOException e) { return 0L; } ClientFailureMsg.requireNon(available <= 0, "无效文件"); ClientFailureMsg.requireNon(dataOffset + available - offset > data.length - dataOffset, "文件过大"); AtomicInteger atomic = new AtomicInteger(dataOffset); return read(i, offset, size, (buffer, len) -> { if (len == 0) return; System.arraycopy(buffer, 0, data, atomic.getAndAccumulate(len, Integer::sum), len); }, dataSize, f); } public static long read(I i, int dataSize, byte[] data, int dataOffset, Consumer f) { return read(i, 0L, 0L, dataSize, data, dataOffset, f); } public static long read(I i, byte[] bytes, int dataOffset) { return read(i, DEFAULT_DATA_SIZE, bytes, dataOffset, null); } public static byte[] read(I i, long offset, long size, int dataSize, Consumer f) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); read(i, offset, size, baos, dataSize, null, (ii, oo) -> { close(oo); if (f == null) close(ii); else f.accept(ii); }); return baos.toByteArray(); } public static byte[] read(I i, int dataSize, Consumer f) { return read(i, 0L, 0L, dataSize, f); } public static byte[] read(I i) { return read(i, DEFAULT_DATA_SIZE, null); } public static
void read(BR br, Collection strings, Consumer
f) { read(br, strings::add, f); } public static
void read(BR br, Collection strings) { read(br, strings, null); } public static
String read(BR br) { StringWriter sw = new StringWriter(); read(br, sw); return sw.toString(); } /////////////////////////////////////////////OutputStream public static void write(O o, byte[] bytes, Consumer f) { try { if (bytes.length > 0) o.write(bytes); flush(o); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(o); else f.accept(o); } catch (Throwable ignored) { } } } public static void write(O o, byte[] bytes) { write(o, bytes, null); } public static void write(O o, Supplier supplier, int dataSize, Consumer f) { try { byte[] buffer = new byte[dataSize]; int idx = 0; ZBTag zbTag; while ((zbTag = supplier.get()) != null && zbTag.isTag()) { buffer[idx++] = zbTag.getData(); if (idx == dataSize) { idx = 0; o.write(buffer); } } if (idx > 0) o.write(buffer, 0, idx); flush(o); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(o); else f.accept(o); } catch (Throwable ignored) { } } } public static void write(O o, Supplier supplier) { write(o, supplier, DEFAULT_DATA_SIZE, null); } public static void writeNull(O o, Supplier supplier, Consumer f) { try { byte[] bytes; while ((bytes = supplier.get()) != null) o.write(bytes); flush(o); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(o); else f.accept(o); } catch (Throwable ignored) { } } } public static void writeNull(O o, Supplier supplier) { writeNull(o, supplier, null); } public static void write(O o, Collection bytes, Consumer f) { try { for (byte[] bs : bytes) if (bs != null) o.write(bs); flush(o); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(o); else f.accept(o); } catch (Throwable ignored) { } } } public static void write(O o, Collection bytes) { write(o, bytes, null); } /////////////////////////////////////////////Writer public static void write(W w, char[] chars, Consumer f) { try { if (chars.length > 0) w.write(chars); flush(w); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(w); else f.accept(w); } catch (Throwable ignored) { } } } public static void write(W w, char[] chars) { write(w, chars, null); } public static void writeChars(W w, Supplier supplier, int bufferSize, Consumer f) { try { char[] buffer = new char[bufferSize]; int idx = 0; ZCTag zcTag; while ((zcTag = supplier.get()) != null && zcTag.isTag()) { buffer[idx++] = zcTag.getData(); if (idx == bufferSize) { idx = 0; w.write(buffer); } } if (idx > 0) w.write(buffer, 0, idx); flush(w); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(w); else f.accept(w); } catch (Throwable ignored) { } } } public static void writeChars(W w, Supplier supplier) { writeChars(w, supplier, DEFAULT_BUFFER_SIZE, null); } public static void writeString(W w, Supplier> supplier, Consumer f) { try { ZLTag zlTag; while ((zlTag = supplier.get()) != null && zlTag.isTag()) w.write(zlTag.getData()); flush(w); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(w); else f.accept(w); } catch (Throwable ignored) { } } } public static void writeString(W w, Supplier> supplier) { writeString(w, supplier, null); } public static void writeNonNull(W w, Supplier supplier, Consumer f) { try { String str; while ((str = supplier.get()) != null) w.write(str); flush(w); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(w); else f.accept(w); } catch (Throwable ignored) { } } } public static void writeNonNull(W w, Supplier supplier) { writeNonNull(w, supplier, null); } public static void write(W w, Collection strings, Consumer f) { try { for (String str : strings) if (str != null) w.write(str); flush(w); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(w); else f.accept(w); } catch (Throwable ignored) { } } } public static void write(W w, Collection strings) { write(w, strings, null); } /////////////////////////////////////////////BufferedWriter public static void write(BW bw, char[] chars, Consumer f) { try { if (chars.length > 0) { bw.write(chars); bw.newLine(); } flush(bw); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(bw); else f.accept(bw); } catch (Throwable ignored) { } } } public static void write(BW bw, char[] chars) { write(bw, chars, null); } public static void write(BW bw, Supplier> supplier, Consumer f) { try { ZLTag zlTag; while ((zlTag = supplier.get()) != null && zlTag.isTag()) { bw.write(zlTag.getData()); bw.newLine(); } flush(bw); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(bw); else f.accept(bw); } catch (Throwable ignored) { } } } public static void write(BW bw, Supplier> supplier) { write(bw, supplier, null); } public static void writeNonNull(BW bw, Supplier supplier, Consumer f) { try { String str; while ((str = supplier.get()) != null) { bw.write(str); bw.newLine(); } flush(bw); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(bw); else f.accept(bw); } catch (Throwable ignored) { } } } public static void writeNonNull(BW bw, Supplier supplier) { writeNonNull(bw, supplier, null); } public static void write(BW bw, Collection strings, Consumer f) { try { for (String str : strings) { if (str != null) { bw.write(str); bw.newLine(); } } flush(bw); } catch (Exception e) { throw PRException.of(e); } finally { try { if (f == null) close(bw); else f.accept(bw); } catch (Throwable ignored) { } } } public static void write(BW bw, Collection strings) { write(bw, strings, null); } }