//============================================================================== // ASALineWriter.java //============================================================================== package tribble.io; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.InputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PushbackInputStream; import java.io.Writer; import java.lang.ArrayIndexOutOfBoundsException; import java.lang.Exception; import java.lang.Integer; import java.lang.NullPointerException; import java.lang.Object; import java.lang.String; import java.lang.System; import java.lang.Throwable; /******************************************************************************* * ASA line printer output stream. * These methods interpret ASA (ANS) printer form control characters in the first * column of each output line. * *

* ASA (ANS) printer form control characters perform some action affecting the * position of the logical printing mechanism prior to printing the remaining * contents of line. The control characters are: *

*

* * * * * * * * * * * * * * CR LF * * * * CR LF CR LF * * * * CR LF CR LF CR LF * * * * * * *
Char Action ASCII Equivalent
1 Advance the page (form feed) FF
space Advance one line
0 Advance two lines
- Advance three lines
+ Do not advance any lines,
overprint the previous line
CR
*

* *

* In place of CR LF sequences to advance to the next line, * the native newline character sequence is used (which could be CR, * CR LF, or LF sequences). *

* *

* The output methods are synchronized, so that when multiple threads write text * lines to the same line printer stream, each line is written atomically. * The resulting output will contain interspersed output lines, with no split or * incomplete lines. *

* *

* Source code *

*

* david.tribble.com/src/java/tribble/io/ASALineWriter.java
* david.tribble.com/src/java. *

* *

* * @version $Revision: 1.2 $ $Date: 2007/12/16 05:25:00 $ * @since API 1.0, 2007-12-12 * @author David R. Tribble (david@tribble.com). *

* Copyright ©2007 by David R. Tribble, all rights reserved.
* Permission is granted to any person or entity except those designated * by the United States Department of State as a terrorist, or terrorist * government or agency, to use and distribute this source code provided * that the original copyright notice remains present and unaltered. *

*/ public class ASALineWriter { /** Revision information. */ static final String REV = "@(#)tribble/io/ASALineWriter.java $Revision: 1.2 $ $Date: 2007/12/16 05:25:00 $\n"; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Constants /** Platform-specific end-of-line (newline) character sequence. */ private static final String EOLN = System.getProperty("line.separator"); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Static methods /*************************************************************************** * Convert an ASA printer file into ASCII. * * @since 1.2, 2007-12-15 */ public static void main(String[] args) throws IOException { ASALineWriter out; int recLen = 80; char[] buf; int i; // Check command line options for (i = 0; i < args.length && args[i].charAt(0) == '-'; i++) { if (args[i].equals("-r")) recLen = Integer.parseInt(args[++i]); else throw new IOException("Bad command option: '" + args[i] + "'"); } // Check command line args if (i >= args.length) { System.out.println("Convert an ASA printer file into ASCII."); System.out.println(); System.out.println("usage: java " + ASALineWriter.class.getName() + " [-option...] file..."); System.out.println(); System.out.println("Options:"); System.out.println(" -r num " + "Fixed input record length (default is 80)"); System.exit(255); } // Open the output stream out = new ASALineWriter( new BufferedWriter(new OutputStreamWriter(System.out))); buf = new char[recLen]; // Process input files for ( ; i < args.length; i++) { PushbackInputStream in; // Process the next filename in = new PushbackInputStream(new FileInputStream(args[i])); for (;;) { int len; // Read a printer text line len = readLine(in, buf); if (len < 0) break; // Write the line to the output stream out.writeLine(buf, 0, len); } // Done in.close(); } // Clean up out.close(); } /*************************************************************************** * Read a fixed-length text line from a printer file. * This is a helper method for {@link #main main()}. * * @since 1.2, 2007-12-15 */ private static int readLine(PushbackInputStream in, char[] buf) throws IOException { int len; // Read a printer text line len = 0; while (len < buf.length) { int ch; ch = in.read(); if (ch < 0) { if (len < 1) return (-1); break; } if (ch == '\r') { ch = in.read(); if (ch != '\n') in.unread(ch); break; } else if (ch == '\n') break; else buf[len++] = (char) ch; } return (len); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Variables /** Output stream. */ private Writer m_out; /** Lock object. */ private Object m_lock; /** Lines written. */ private int m_nLines; /** Pages written. */ private int m_nPages; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Constructors /*************************************************************************** * Constructor. * * @param out * Underlying output stream. * All I/O operations will synchronize on this object. * * @throws NullPointerException (unchecked) * Thrown if out is null. * * @since 1.1, 2007-12-12 */ public ASALineWriter(Writer out) { this(out, out); } /*************************************************************************** * Constructor. * * @param out * Underlying output stream. * * @param lock * All I/O operations will synchronize on this object. * This can be null, in which case all I/O operations synchronize on the line * printer object itself. * * @throws NullPointerException (unchecked) * Thrown if out is null. * * @since 1.1, 2007-12-12 */ public ASALineWriter(Writer out, Object lock) { // Sanity checks if (out == null) throw new NullPointerException(); if (lock == null) lock = this; // Initialize m_out = out; m_lock = lock; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Methods /*************************************************************************** * Finalization. * * @since 1.1, 2007-12-12 */ protected synchronized void finalize() throws Throwable { try { close(); } catch (IOException ex) { } super.finalize(); } /*************************************************************************** * Close the output stream. * * @throws IOException * Thrown if an I/O write error occurs. * * @since 1.1, 2007-12-12 */ public void close() throws IOException { if (m_out != null) { synchronized (m_lock) { // Write a final end-of-line to the output stream if (m_nLines > 0) m_out.write(EOLN); // Close the output stream m_out.close(); } m_out = null; m_lock = null; } } /*************************************************************************** * Write any pending output to the output stream. * * @throws IOException * Thrown if an I/O write error occurs. * * @since 1.1, 2007-12-12 */ public void flush() throws IOException { if (m_out == null) throw new IOException("Output stream is closed"); synchronized (m_lock) { m_out.flush(); } } /*************************************************************************** * Write a line of characters to the output stream. * Note that the characters are written as a complete text line, and that the * first character (line.charAt(0)) is the ASA form control * character for the line. * * @param line * Text line to write. * Note that other than the first character, the contents of this line are * not interpreted. This implies that non-printing characters (especially * '\n', '\r', and '\f' characters) will produce * unexpected results. * * @throws IOException * Thrown if an I/O write error occurs. * * @since 1.1, 2007-12-12 */ public void writeLine(String line) throws IOException { // Sanity checks if (m_out == null) throw new IOException("Output stream is closed"); // Write the text line to the output stream if (line.length() < 1) line = " "; synchronized (m_lock) { writeCtrl(line.charAt(0)); m_out.write(line, 1, line.length() - 1); m_nLines++; } } /*************************************************************************** * Write a line of characters to the output stream. * Note that the characters are written as a complete text line, and that the * first character (line.charAt(off)) is the ASA form control * character for the line. * * @param line * Text line to write. * Note that other than the first character, the contents of this line are * not interpreted. This implies that non-printing characters (especially * '\n', '\r', and '\f' characters) will produce * unexpected results. * * @param off * Index of the first character in line to write. * * @param len * Number of characters in line to write. * * @throws IOException * Thrown if an I/O write error occurs. * * @since 1.1, 2007-12-12 */ public void writeLine(String line, int off, int len) throws IOException { // Sanity checks if (m_out == null) throw new IOException("Output stream is closed"); if (len < 1) return; if (off < 0) throw new ArrayIndexOutOfBoundsException(off); if (off+len < 0 || off+len >= line.length()) throw new ArrayIndexOutOfBoundsException(off+len); // Write the text line to the output stream synchronized (m_lock) { writeCtrl(line.charAt(off)); m_out.write(line, off+1, len-1); m_nLines++; } } /*************************************************************************** * Write an empty line to the output stream. * * @throws IOException * Thrown if an I/O write error occurs. * * @since 1.1, 2007-12-12 */ public void writeLine() throws IOException { // Sanity checks if (m_out == null) throw new IOException("Output stream is closed"); // Write an empty line to the output stream synchronized (m_lock) { writeCtrl(' '); m_nLines++; } } /*************************************************************************** * Write a line of characters to the output stream. * Note that the characters are written as a complete text line, and that the * first character (buf[0]) is the ASA form control character for * the line. * * @param buf * Characters to write. * Note that other than the first character, the contents of this line are * not interpreted. This implies that non-printing characters (especially * '\n', '\r', and '\f' characters) will produce * unexpected results. * * @return * The number of characters from buf that were written to the output * stream. * * @throws IOException * Thrown if an I/O write error occurs. * * @since 1.1, 2007-12-12 */ public int writeLine(/*const*/ char[] buf) throws IOException { return (writeLine(buf, 0, buf.length)); } /*************************************************************************** * Write a line of characters to the output stream. * Note that the characters are written as a complete text line, and that the * first character (buf[off]) is the ASA form control character for * the line. * * @param buf * Characters to write. * Note that other than the first character, the contents of this line are * not interpreted. This implies that non-printing characters (especially * '\n', '\r', and '\f' characters) will produce * unexpected results. * * @param off * Index of the first character in buf to write. * * @param len * Number of characters in buf to write. * * @return * The number of characters from buf that were written to the output * stream. * * @throws IOException * Thrown if an I/O write error occurs. * * @since 1.1, 2007-12-12 */ public int writeLine(/*const*/ char[] buf, int off, int len) throws IOException { int cnt; // Sanity checks if (m_out == null) throw new IOException("Output stream is closed"); if (len < 1) return (0); if (off < 0) throw new ArrayIndexOutOfBoundsException(off); if (off+len < 0 || off+len >= buf.length) throw new ArrayIndexOutOfBoundsException(off+len); // Write the text line characters to the output stream synchronized (m_lock) { writeCtrl(buf[off]); if (len > 1) m_out.write(buf, off+1, len-1); m_nLines++; } return (len); } /*************************************************************************** * Write an ASA form control character to the output stream. * * @param ctl * ASA form control character. * * @throws IOException * Thrown if an I/O write error occurs. * * @since 1.1, 2007-12-12 */ private void writeCtrl(char ctl) throws IOException { // Interpret the ASA form control character switch (ctl) { case ' ': default: // Skip 1 line (single spacing) if (m_nLines > 0) m_out.write(EOLN); break; case '1': // Form feed (page eject) if (m_nLines > 0) m_out.write(EOLN); //m_out.flush(); m_out.write('\f'); m_nPages++; break; case '0': // Skip 2 lines if (m_nLines > 0) m_out.write(EOLN); m_out.write(EOLN); m_nLines++; break; case '-': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'A': case 'B': case 'C': // Skip 3 lines if (m_nLines > 0) m_out.write(EOLN); m_out.write(EOLN); m_out.write(EOLN); m_nLines += 2; break; case '+': // Skip no lines, overstrike the previous line if (m_nLines > 0) m_out.write('\r'); break; } } /*************************************************************************** * Retrieve the number of lines written to the output stream. * * @return * Number of lines written to the output stream so far (starting with zero). * * @since 1.1, 2007-12-12 */ public int getLineCount() { return (m_nLines); } /*************************************************************************** * Reset the line counter for the output stream. * * @param n * Line number at which to begin re-counting. * * @since 1.1, 2007-12-15 */ public void setLineCount(int n) { m_nLines = n; } /*************************************************************************** * Retrieve the number of pages written to the output stream. * * @return * Number of pages written to the output stream so far (starting with zero). * * @since 1.1, 2007-12-12 */ public int getPageCount() { return (m_nPages); } /*************************************************************************** * Reset the page counter for the output stream. * * @param n * Page number at which to begin re-counting. * * @since 1.1, 2007-12-15 */ public void setPageCount(int n) { m_nPages = n; } } // End ASALineWriter.java