Java命令行交互客戶端

Java命令行交互客戶端指的是,用java寫的命令行程序,該程序具有良好的交互性,也就是說程序運行時允許用戶輸入參數,執行完後程序並沒有退出,而是繼續等待用戶輸入參數,直到用戶輸入退出命令。就像SQLPlus那樣的效果,用SQLPlus登錄後,用戶可以執行輸入的SQL語句,只要用戶不輸入退出命令,SQLPlus就一直等待用戶輸入SQL語句,執行並繼續等待。需要以下2個Class的支持:

 

1、工具類FormattingPrintWriter

  1. import java.io.BufferedReader;
  2. import java.io.File;
  3. import java.io.InputStreamReader;
  4. import java.io.OutputStream;
  5. import java.io.PrintWriter;
  6. import java.io.Writer;
  7. import java.util.Stack;
  8. public class FormattingPrintWriter extends PrintWriter {
  9.     private static final String NEWLINE = System.getProperty("line.separator",
  10.             "/r/n");
  11.     // Standard tab settings
  12.     private static final int[] STD_TABS = { 91725334149576573,
  13.             81 };
  14.     private boolean _autoFlush;
  15.     private int[] _tabs = STD_TABS;
  16.     @SuppressWarnings("unchecked")
  17.     private Stack _stack = new Stack();
  18.     private int _indent;
  19.     private int _pos;
  20.     /**
  21.      * Returns a string consisting of the specified number of spaces.
  22.      * 
  23.      * @return The requested whitespace string.
  24.      */
  25.     private static String spaces(int n) {
  26.         char[] ca = new char[n];
  27.         for (int i = 0; i < n; i++)
  28.             ca[i] = ' ';
  29.         return new String(ca, 0, ca.length);
  30.     }
  31.     /**
  32.      * Constructs a new FormattingPrintWriter, without automatic line flushing.
  33.      * 
  34.      * @param out
  35.      *            A character-output stream.
  36.      */
  37.     public FormattingPrintWriter(Writer out) {
  38.         super(out);
  39.     }
  40.     /**
  41.      * Constructs a new FormattingPrintWriter.
  42.      * 
  43.      * @param out
  44.      *            A character-output stream.
  45.      * @param autoFlush
  46.      *            If <code>true</code>, the println() methods will flush the
  47.      *            output buffer.
  48.      */
  49.     public FormattingPrintWriter(Writer out, boolean autoFlush) {
  50.         super(out, autoFlush);
  51.         _autoFlush = autoFlush;
  52.     }
  53.     /**
  54.      * Constructs a new PrintWriter, without automatic line flushing, from an
  55.      * existing OutputStream. This convenience constructor creates the necessary
  56.      * intermediate OutputStreamWriter, which will convert characters into bytes
  57.      * using the default character encoding.
  58.      * 
  59.      * @param out
  60.      *            An output stream.
  61.      */
  62.     public FormattingPrintWriter(OutputStream out) {
  63.         super(out);
  64.     }
  65.     /**
  66.      * Constructs a new PrintWriter from an existing OutputStream. This
  67.      * convenience constructor creates the necessary intermediate
  68.      * OutputStreamWriter, which will convert characters into bytes using the
  69.      * default character encoding.
  70.      * 
  71.      * @param out
  72.      *            An output stream.
  73.      * @param autoFlush
  74.      *            if <code>true</code>, the println() methods will flush the
  75.      *            output buffer.
  76.      */
  77.     public FormattingPrintWriter(OutputStream out, boolean autoFlush) {
  78.         super(out, autoFlush);
  79.         _autoFlush = autoFlush;
  80.     }
  81.     /**
  82.      * Restores the default tab stops.
  83.      */
  84.     public void clearTabs() {
  85.         setTabs(null);
  86.     }
  87.     /**
  88.      * Sets custom tab stops. At output positions past the rightmost tab stop,
  89.      * tab characters are converted into single spaces.
  90.      * 
  91.      * @param tabs
  92.      *            Unity-based tab stop positions, as an ascending sequence of
  93.      *            positive integers.
  94.      */
  95.     public void setTabs(int[] tabs) {
  96.         synchronized (lock) {
  97.             if (tabs == null) {
  98.                 _tabs = STD_TABS;
  99.             } else {
  100.                 for (int i = 0, n = tabs.length - 1; i < n; i++) {
  101.                     if (tabs[i] <= 0 || tabs[i] >= tabs[i + 1])
  102.                         throw new IllegalArgumentException(
  103.                                 "Tab stops must be an ascending sequence of positive integers.");
  104.                 }
  105.                 _tabs = new int[tabs.length];
  106.                 System.arraycopy(tabs, 0, _tabs, 0, tabs.length);
  107.             }
  108.             if (_pos != 0)
  109.                 println();
  110.         }
  111.     }
  112.     /**
  113.      * Returns unity-based tab stop positions, as an ascending sequence of
  114.      * positive integers.
  115.      * 
  116.      * @return Current tab stops.
  117.      */
  118.     public int[] getTabs() {
  119.         return (int[]) _tabs.clone();
  120.     }
  121.     /**
  122.      * Increases the indentation level by the specified amount.
  123.      * 
  124.      * @param i
  125.      *            Number of columns by which to increase indentation.
  126.      */
  127.     @SuppressWarnings("unchecked")
  128.     public void pushIndent(int i) {
  129.         if (i <= 0) {
  130.             throw new IllegalArgumentException(
  131.                     "Indentation must be a positive integer");
  132.         }
  133.         synchronized (lock) {
  134.             _stack.push(new Integer(i));
  135.             _indent += i;
  136.         }
  137.     }
  138.     /**
  139.      * Increases the indentation level to the next tab stop past the current
  140.      * output position.
  141.      */
  142.     public void pushIndent() {
  143.         // Indent to the nearest tab stop to the right of the current
  144.         // indentation level, if such a tab stop exists.
  145.         for (int i = 0, n = _tabs.length; i < n; i++)
  146.             if (_tabs[i] > _indent) {
  147.                 pushIndent(_tabs[i] - _indent);
  148.                 return;
  149.             }
  150.         // Past the rightmost tab stop, indentation is one space.
  151.         pushIndent(1);
  152.     }
  153.     /**
  154.      * Restores the previous indentation level.
  155.      * 
  156.      * @throws IllegalStateException
  157.      *             if the current indentation level is 0.
  158.      */
  159.     public void popIndent() {
  160.         if (_stack.empty())
  161.             throw new IllegalStateException();
  162.         _indent -= ((Integer) _stack.pop()).intValue();
  163.     }
  164.     /**
  165.      * Returns the current indentation level.
  166.      * 
  167.      * @return Indentation level as a character count.
  168.      */
  169.     public int getIndent() {
  170.         return _indent;
  171.     }
  172.     /**
  173.      * Returns the current output position (zero-based).
  174.      * 
  175.      * @return The output position.
  176.      */
  177.     public int getPosition() {
  178.         return _pos;
  179.     }
  180.     /**
  181.      * Expands a tab character by setting the output position to the next tab
  182.      * stop past the current output position.
  183.      * 
  184.      * @return Space-filled string.
  185.      */
  186.     private String expandTab() {
  187.         // If pos is after the last tab stop, translate tab characters to
  188.         // spaces.
  189.         String s = " ";
  190.         int curpos = _indent + _pos;
  191.         for (int i = 0; i < _tabs.length; i++) {
  192.             // Tab stops use 1-based column numbers,
  193.             if (_tabs[i] - 1 > curpos) {
  194.                 // curpos is a 0-based column index.
  195.                 s = spaces(_tabs[i] - curpos - 1);
  196.                 break;
  197.             }
  198.         }
  199.         _pos += s.length();
  200.         return s;
  201.     }
  202.     /**
  203.      * Expands embedded tab and newline escape sequences, adjusting the output
  204.      * position accordingly. The method recognizes 'C'/Java-style '/t', '/r' and
  205.      * '/n' escape sequences.
  206.      * 
  207.      * @param ch
  208.      *            Character to expand.
  209.      * @return String containing (expanded) input character.
  210.      */
  211.     private String expandEscapes(char ch) {
  212.         StringBuffer result = new StringBuffer();
  213.         switch (ch) {
  214.         case '/t':
  215.             if (_pos == 0 && _indent > 0)
  216.                 result.append(spaces(_indent));
  217.             result.append(expandTab());
  218.             break;
  219.         case '/n':
  220.             _pos = 0;
  221.         case '/r':
  222.             result.append(ch);
  223.             break;
  224.         default:
  225.             if (_pos == 0 && _indent > 0)
  226.                 result.append(spaces(_indent));
  227.             result.append(ch);
  228.             _pos++;
  229.         }
  230.         return result.toString();
  231.     }
  232.     /**
  233.      * Expands embedded tab and newline escape sequences, adjusting the output
  234.      * position accordingly. The method recognizes 'C'/Java-style '/t', '/r' and
  235.      * '/n' escape sequences.
  236.      * 
  237.      * @param s
  238.      *            Source string.
  239.      * @param off
  240.      *            Offset at which to start copying.
  241.      * @param len
  242.      *            Number of source characters to process.
  243.      * @return Copy of the source string where all escape sequences have been
  244.      *         replaced by their equivalent characters.
  245.      */
  246.     private String expandEscapes(String s, int off, int len) {
  247.         StringBuffer result = new StringBuffer(len);
  248.         for (int i = off, end = off + len; i < end; i++) {
  249.             char ch = s.charAt(i);
  250.             switch (ch) {
  251.             case '/t':
  252.                 if (_pos == 0 && _indent > 0)
  253.                     result.append(spaces(_indent));
  254.                 result.append(expandTab());
  255.                 break;
  256.             case '/n':
  257.                 _pos = 0;
  258.             case '/r':
  259.                 result.append(ch);
  260.                 break;
  261.             default:
  262.                 if (_pos == 0 && _indent > 0)
  263.                     result.append(spaces(_indent));
  264.                 result.append(ch);
  265.                 _pos++;
  266.             }
  267.         }
  268.         return result.toString();
  269.     }
  270.     /**
  271.      * Writes a character, which may be a tab or newline.
  272.      * 
  273.      * @param c
  274.      *            Character to write.
  275.      */
  276.     private void _writeEx(int c) {
  277.         String s = expandEscapes((char) c);
  278.         super.write(s, 0, s.length());
  279.     }
  280.     /**
  281.      * Writes a string which may contain tab or newline characters.
  282.      * 
  283.      * @param s
  284.      *            Source string.
  285.      * @param off
  286.      *            Offset at which to start writing.
  287.      * @param len
  288.      *            Number of source characters to process.
  289.      */
  290.     private void _writeEx(String s, int off, int len) {
  291.         s = expandEscapes(s, off, len);
  292.         super.write(s, 0, s.length());
  293.     }
  294.     /**
  295.      * Writes a string that does not contain embedded tabs or newlines.
  296.      * 
  297.      * @param s
  298.      *            Source string.
  299.      * @param off
  300.      *            Offset at which to start writing.
  301.      * @param len
  302.      *            Number of source characters to process.
  303.      */
  304.     private void _write(String s, int off, int len) {
  305.         _pos += len;
  306.         super.write(s, off, len);
  307.     }
  308.     public void print(boolean b) {
  309.         String s = String.valueOf(b);
  310.         _write(s, 0, s.length());
  311.     }
  312.     public void print(char c) {
  313.         _writeEx(c);
  314.     }
  315.     public void print(int i) {
  316.         String s = String.valueOf(i);
  317.         _write(s, 0, s.length());
  318.     }
  319.     public void print(long l) {
  320.         String s = String.valueOf(l);
  321.         _write(s, 0, s.length());
  322.     }
  323.     public void print(float f) {
  324.         String s = String.valueOf(f);
  325.         _write(s, 0, s.length());
  326.     }
  327.     public void print(double d) {
  328.         String s = String.valueOf(d);
  329.         _write(s, 0, s.length());
  330.     }
  331.     public void print(char[] ca) {
  332.         _writeEx(new String(ca), 0, ca.length);
  333.     }
  334.     public void print(String s) {
  335.         _writeEx(s, 0, s.length());
  336.     }
  337.     public void print(Object obj) {
  338.         String s = String.valueOf(obj);
  339.         _writeEx(s, 0, s.length());
  340.     }
  341.     private void newLine() {
  342.         _write(NEWLINE, 0, NEWLINE.length());
  343.         _pos = 0;
  344.         if (_autoFlush)
  345.             flush();
  346.     }
  347.     public void println() {
  348.         synchronized (lock) {
  349.             newLine();
  350.         }
  351.     }
  352.     public void println(boolean b) {
  353.         synchronized (lock) {
  354.             print(b);
  355.             newLine();
  356.         }
  357.     }
  358.     public void println(char c) {
  359.         synchronized (lock) {
  360.             print(c);
  361.             newLine();
  362.         }
  363.     }
  364.     public void println(int i) {
  365.         synchronized (lock) {
  366.             print(i);
  367.             newLine();
  368.         }
  369.     }
  370.     public void println(long l) {
  371.         synchronized (lock) {
  372.             print(l);
  373.             newLine();
  374.         }
  375.     }
  376.     public void println(float f) {
  377.         synchronized (lock) {
  378.             print(f);
  379.             newLine();
  380.         }
  381.     }
  382.     public void println(double d) {
  383.         synchronized (lock) {
  384.             print(d);
  385.             newLine();
  386.         }
  387.     }
  388.     public void println(char[] c) {
  389.         synchronized (lock) {
  390.             print(c);
  391.             newLine();
  392.         }
  393.     }
  394.     public void println(String s) {
  395.         synchronized (lock) {
  396.             print(s);
  397.             newLine();
  398.         }
  399.     }
  400.     public void println(Object obj) {
  401.         synchronized (lock) {
  402.             print(obj);
  403.             newLine();
  404.         }
  405.     }
  406.     public void write(int c) {
  407.         _writeEx(c);
  408.     }
  409.     public void write(char[] buf, int off, int len) {
  410.         _writeEx(new String(buf, off, len), 0, len);
  411.     }
  412.     public void write(char[] buf) {
  413.         _writeEx(new String(buf), 0, buf.length);
  414.     }
  415.     public void write(String s, int off, int len) {
  416.         _writeEx(s, off, len);
  417.     }
  418.     public void write(String s) {
  419.         _writeEx(s, 0, s.length());
  420.     }
  421.     public static void main(String[] args) throws Exception {
  422.         System.out.println("please enter file path");
  423.         BufferedReader stdin = new BufferedReader(new InputStreamReader(
  424.                 System.in));
  425.         String line = null;
  426.         while ((line = stdin.readLine()) != null) {
  427.             File dir = new File(line.trim());
  428.             if (dir.exists()) {
  429.                 System.out.println(dir.getAbsolutePath());
  430.                 break;
  431.             } else {
  432.                 System.out.println("dir does not exist,please re-enter:");
  433.             }
  434.         }
  435.     }
  436. }

2、客戶端監聽類CommandClient

  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStreamReader;
  4. import java.lang.reflect.InvocationTargetException;
  5. import java.lang.reflect.Method;
  6. import java.util.HashMap;
  7. import java.util.Map;
  8. @SuppressWarnings("unchecked")
  9. public class CommandClient {
  10.     private String title = "Java命令行客戶端";
  11.     private Class listenClass = this.getClass();
  12.     private BufferedReader _stdin;
  13.     private FormattingPrintWriter _stdout;
  14.     // 默認主菜單
  15.     private Object[][] MENU = {
  16.         // 命令符, 描述, 要調用的方法
  17.         { "1""歡迎""welcome" },
  18.         { "Q""退出""quit" } 
  19.         };
  20.     public CommandClient(Class clazz) {
  21.         if(clazz != null){
  22.             this.listenClass = clazz;
  23.         }
  24.         
  25.         _stdin = new BufferedReader(new InputStreamReader(System.in));
  26.         _stdout = new FormattingPrintWriter(System.out, true);
  27.         _stdout.println("/n==== " + this.title + " ====");
  28.     }
  29.     
  30.     public CommandClient(String title, Class clazz) {
  31.         if(clazz != null){
  32.             this.listenClass = clazz;
  33.         }
  34.         _stdin = new BufferedReader(new InputStreamReader(System.in));
  35.         _stdout = new FormattingPrintWriter(System.out, true);
  36.         if(title != null && !title.trim().equals("")){
  37.             this.title = title;
  38.         }
  39.         _stdout.println("/n==== " + this.title + " ====");
  40.     }
  41.     
  42.     public void setMenu(Object[][] menu){
  43.         if(menu != null){
  44.             this.MENU = menu;
  45.         }
  46.     }
  47.     
  48.     @SuppressWarnings("unchecked")
  49.     private Method findMethod(String name) {
  50.         Class cl = this.listenClass;
  51.         Method method = null;
  52.         while (method == null) {
  53.             try {
  54.                 method = cl.getDeclaredMethod(name, null);
  55.             } catch (NoSuchMethodException e) {
  56.                 System.out.println("no method define");
  57.                 cl = cl.getSuperclass();
  58.                 if (cl == null) {
  59.                     e.printStackTrace();
  60.                     System.exit(1);
  61.                 }
  62.             }
  63.         }
  64.         
  65.         return method;
  66.     }
  67.     private String getChoice(String choices) throws IOException {
  68.         while (true) {
  69.             _stdout.print("> ");
  70.             _stdout.flush();
  71.             String line = _stdin.readLine().trim();
  72.             if (line.length() == 1) {
  73.                 int choice = Character.toUpperCase(line.charAt(0));
  74.                 int index = choices.indexOf(choice);
  75.                 if (index != -1)
  76.                     return choices.substring(index, index + 1);
  77.             }
  78.             _stdout.println("/n*** 必須選擇以下選項之一: " + choices);
  79.         }
  80.     }
  81.     // 選擇菜單選項,動態調用某個方法
  82.     public void doMenu(Object[][] menu, boolean main) {
  83.         this.doMenu(title, this.MENU, main);
  84.     }
  85.     @SuppressWarnings("unchecked")
  86.     public void doMenu(String pTitle, Object[][] menu, boolean main) {
  87.         synchronized (System.in) {
  88.             Map actions = new HashMap();
  89.             StringBuffer sb = new StringBuffer(menu.length);
  90.             for (int i = 0; i < menu.length; i++) {
  91.                 Object mnemonic = menu[i][0];
  92.                 sb.append(mnemonic);
  93.                 Object action = menu[i][2];
  94.                 if (action instanceof String)
  95.                     action = findMethod((String) action);
  96.                 actions.put(mnemonic, action);
  97.             }
  98.             String choices = sb.toString();
  99.             while (true) {
  100.                 try {
  101.                     String mnemonic;
  102.                     _stdout.clearTabs();
  103.                     _stdout.println("/n---   " + pTitle + "   ---");
  104.                     _stdout.println("/n請選擇菜單項:");
  105.                     for (int i = 0; i < menu.length; i++)
  106.                         _stdout.println("[" + menu[i][0] + "]  " + menu[i][1]);
  107.                     // Get the user's selection.
  108.                     mnemonic = getChoice(choices);
  109.                     // System.out.println("mnemonic = " + mnemonic);
  110.                     for (int i = 0; i < menu.length; i++) {
  111.                         Object[] entry = menu[i];
  112.                         if (entry[0].equals(mnemonic)) {
  113.                             Object action = actions.get(mnemonic);
  114.                             if (action == null) {
  115.                                 return;
  116.                             } else if (action instanceof Method) {
  117.                                 // System.out.println("selected,will do");
  118.                                 // Cast required to suppress JDK1.5 varargs
  119.                                 // compiler warning.
  120.                                 ((Method) action).invoke(this, (Object[]) null);
  121.                             } else {
  122.                                 doMenu((String) entry[1], (Object[][]) action, false);
  123.                             }
  124.                         }
  125.                     }
  126.                 } catch (Exception e) {
  127.                     Throwable t = e;
  128.                     if (e instanceof InvocationTargetException)
  129.                         t = ((InvocationTargetException) e)
  130.                                 .getTargetException();
  131.                     _stdout.println("/n發生異常: " + t);
  132.                 }
  133.             }// while end
  134.         }
  135.     }
  136.     
  137.     public void run(Object[][] menu){
  138.         this.setMenu(menu);
  139.         this.doMenu(menu, true);
  140.     }
  141.     
  142.     public void welcome(){
  143.         System.out.println("歡迎使用Java命令行客戶端!");
  144.     }
  145.     
  146.     public void quit() {
  147.         System.exit(0);
  148.     }
  149.     
  150.     public static void main(String[] args) {
  151.         CommandClient client = new CommandClient(null);
  152.         client.doMenu(nulltrue);
  153.     }
  154. }

3、使用示例:

  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStreamReader;
  4. public class Main {
  5.     public static void main(String[] args) {
  6.         // 返回菜單 
  7.         Object[] BACK = { "B""回到上級菜單"null };
  8.         // 二級菜單 -- 數學計算 
  9.         Object[][] SXJS_MENU = {
  10.                 // 命令符, 描述, 要調用的方法 
  11.                 { "1""求和""add" },
  12.                 { "2""求差""sub" },
  13.                 BACK,
  14.                 { "Q""退出""quit" }
  15.                 };
  16.         
  17.         // 主菜單 
  18.         Object[][] MENU = {
  19.                 // 命令符, 描述, 要調用的方法 
  20.                 { "1""數學計算", SXJS_MENU },
  21.                 { "2""打印消息""print" },
  22.                 { "3""使用幫助""help" },
  23.                 { "Q""退出""quit" }
  24.         };
  25.         
  26.         CommandClient client = new CommandClient(Main.class);
  27.         client.run(MENU);
  28.     }
  29.     /**
  30.      * 求和
  31.      */
  32.     public static void add(){
  33.         try {
  34.             BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
  35.             System.out.print("請輸入第一個數字:");
  36.             String one = in.readLine();
  37.             System.out.print("請輸入第二個數字:");
  38.             String two = in.readLine();
  39.             
  40.             System.out.println(one + " + " + two + " = " + (Integer.parseInt(one) + Integer.parseInt(two)));
  41.         } catch (IOException e) {
  42.             e.printStackTrace();
  43.         }
  44.     }
  45.     
  46.     /**
  47.      * 求差
  48.      */
  49.     public static void sub(){
  50.         try {
  51.             BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
  52.             System.out.print("請輸入第一個數字:");
  53.             String one = in.readLine();
  54.             System.out.print("請輸入第二個數字:");
  55.             String two = in.readLine();
  56.             
  57.             System.out.println(one + " - " + two + " = " + (Integer.parseInt(one) - Integer.parseInt(two)));
  58.         } catch (IOException e) {
  59.             e.printStackTrace();
  60.         }
  61.     }
  62.     
  63.     /**
  64.      * 打印消息
  65.      */
  66.     public static void print(){
  67.         try {
  68.             BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
  69.             System.out.print("請輸入要輸出的消息:");
  70.             String msg = in.readLine();
  71.             System.out.println(msg);
  72.         } catch (IOException e) {
  73.             e.printStackTrace();
  74.         }
  75.     }
  76.     
  77.     /**
  78.      * 幫助
  79.      */
  80.     public static void help(){
  81.         System.out.println("先選擇菜單向(括號中的符號),根據提示輸入。");
  82.     }
  83.     /**
  84.      * 退出
  85.      */
  86.     public static void quit(){
  87.         System.out.println("Bye!");
  88.         System.exit(0);
  89.     }
  90.     
  91. }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章