package org.marketcetera.util.file; import java.io.IOException; import java.io.Reader; import java.io.Writer; import org.apache.commons.io.IOUtils; import org.marketcetera.util.except.ExceptUtils; import org.marketcetera.util.except.I18NException; import org.marketcetera.util.log.I18NBoundMessage1P; import org.marketcetera.util.log.I18NBoundMessage2P; import org.marketcetera.util.misc.ClassVersion; import org.marketcetera.util.unicode.DecodingStrategy; import org.marketcetera.util.unicode.SignatureCharset; import org.marketcetera.util.unicode.UnicodeInputStreamReader; /** * Utilities for copying textual data, with Unicode BOM support. The * participating media include files, arrays, readers/writers, or some * combinations thereof. * * @author tlerios@marketcetera.com * @since 0.6.0 * @version $Id: CopyCharsUnicodeUtils.java 16154 2012-07-14 16:34:05Z colin $ */ /* $License$ */ @ClassVersion("$Id: CopyCharsUnicodeUtils.java 16154 2012-07-14 16:34:05Z colin $") public final class CopyCharsUnicodeUtils { // CLASS METHODS. /** * Copies a character stream from one given location (and * interpreted using the given strategy) to another, attempting to * retain signature/charset information. * * @param in The name of the character source, as interpreted by * {@link ReaderWrapper#ReaderWrapper(String,DecodingStrategy)}. * @param decodingStrategy The decoding strategy. It may be null * to use the default JVM charset. * @param out The name of the character sink, as interpreted by * {@link WriterWrapper#WriterWrapper(String,SignatureCharset)}. * * @return The number of characters copied. * * @throws I18NException Thrown if there is a data read/write * error. */ public static long copy (String in, DecodingStrategy decodingStrategy, String out) throws I18NException { CloseableRegistry registry=new CloseableRegistry(); try { ReaderWrapper inW=new ReaderWrapper(in,decodingStrategy); registry.register(inW); Reader reader=inW.getReader(); SignatureCharset sc=null; if (reader instanceof UnicodeInputStreamReader) { sc=((UnicodeInputStreamReader)reader).getSignatureCharset(); } WriterWrapper outW=new WriterWrapper(out,sc); registry.register(outW); return IOUtils.copyLarge(inW.getReader(),outW.getWriter()); } catch (IOException ex) { throw ExceptUtils.wrap(ex,new I18NBoundMessage2P (Messages.CANNOT_COPY_FILES,in,out)); } finally { registry.close(); } } /** * Copies a character stream from the given source to the given * location, attempting to retain signature/charset information. * * @param in The character source, as interpreted by {@link * ReaderWrapper#ReaderWrapper(Reader,boolean)}. * @param skipClose True if the source reader should not be * closed. * @param out The name of the character sink, as interpreted by * {@link WriterWrapper#WriterWrapper(String,SignatureCharset)}. * * @return The number of characters copied. * * @throws I18NException Thrown if there is a data read/write * error. */ public static long copy (Reader in, boolean skipClose, String out) throws I18NException { CloseableRegistry registry=new CloseableRegistry(); try { ReaderWrapper inW=new ReaderWrapper(in,skipClose); registry.register(inW); SignatureCharset sc=null; if (in instanceof UnicodeInputStreamReader) { sc=((UnicodeInputStreamReader)in).getSignatureCharset(); } WriterWrapper outW=new WriterWrapper(out,sc); registry.register(outW); return IOUtils.copyLarge(inW.getReader(),outW.getWriter()); } catch (IOException ex) { throw ExceptUtils.wrap(ex,new I18NBoundMessage1P (Messages.CANNOT_COPY_READER,out)); } finally { registry.close(); } } /** * Copies a character stream from the given location (and * interpreted using the given strategy) to the given sink. * * @param in The name of the character source, as interpreted by {@link * ReaderWrapper#ReaderWrapper(String,DecodingStrategy)}. * @param decodingStrategy The decoding strategy. It may be null * to use the default JVM charset. * @param out The character sink, as interpreted by {@link * WriterWrapper#WriterWrapper(Writer,boolean)}. * @param skipClose True if the sink writer should not be closed. * * @return The number of characters copied. * * @throws I18NException Thrown if there is a data read/write * error. */ public static long copy (String in, DecodingStrategy decodingStrategy, Writer out, boolean skipClose) throws I18NException { CloseableRegistry registry=new CloseableRegistry(); try { ReaderWrapper inW=new ReaderWrapper(in,decodingStrategy); registry.register(inW); WriterWrapper outW=new WriterWrapper(out,skipClose); registry.register(outW); return IOUtils.copyLarge(inW.getReader(),outW.getWriter()); } catch (IOException ex) { throw ExceptUtils.wrap(ex,new I18NBoundMessage1P (Messages.CANNOT_COPY_WRITER,in)); } finally { registry.close(); } } /** * Copies the character stream at the given location (and * interpreted using the given strategy) into memory, returning a * character array. * * @param name The name of the character source, as interpreted by * {@link ReaderWrapper#ReaderWrapper(String,DecodingStrategy)}. * @param decodingStrategy The decoding strategy. It may be null * to use the default JVM charset. * * @return The array. * * @throws I18NException Thrown if there is a data read/write * error. */ public static char[] copy (String name, DecodingStrategy decodingStrategy) throws I18NException { try { ReaderWrapper inW=new ReaderWrapper(name,decodingStrategy); try { return IOUtils.toCharArray(inW.getReader()); } finally { inW.close(); } } catch (IOException ex) { throw ExceptUtils.wrap(ex,new I18NBoundMessage1P (Messages.CANNOT_COPY_MEMORY_DST,name)); } } /** * Copies an in-memory character array into the given location and * using the given signature/charset. * * @param data The array. * @param name The name of the character sink, as interpreted by * {@link WriterWrapper#WriterWrapper(String,SignatureCharset)}. * @param requestedSignatureCharset The signature/charset. It may * be null to use the default JVM charset. * * @throws I18NException Thrown if there is a data read/write * error. */ public static void copy (char[] data, String name, SignatureCharset requestedSignatureCharset) throws I18NException { try { WriterWrapper outW=new WriterWrapper (name,requestedSignatureCharset); try { outW.getWriter().write(data); } finally { outW.close(); } } catch (IOException ex) { throw ExceptUtils.wrap(ex,new I18NBoundMessage1P (Messages.CANNOT_COPY_MEMORY_SRC,name)); } } // CONSTRUCTOR. /** * Constructor. It is private so that no instances can be created. */ private CopyCharsUnicodeUtils() {} }