📄 printfformat.java
字号:
* Release 1: Initial release. * Release 2: Asterisk field widths and precisions * %n$ and *m$ * Bug fixes * g format fix (2 digits in e form corrupt) * rounding in f format implemented * round up when digit not printed is 5 * formatting of -0.0f * round up/down when last digits are 50000... */public class PrintfFormat { /** * Constructs an array of control specifications * possibly preceded, separated, or followed by * ordinary strings. Control strings begin with * unpaired percent signs. A pair of successive * percent signs designates a single percent sign in * the format. * @param fmtArg Control string. * @exception IllegalArgumentException if the control * string is null, zero length, or otherwise * malformed. */ public PrintfFormat(String fmtArg) throws IllegalArgumentException { this(Locale.getDefault(), fmtArg); } /** * Constructs an array of control specifications * possibly preceded, separated, or followed by * ordinary strings. Control strings begin with * unpaired percent signs. A pair of successive * percent signs designates a single percent sign in * the format. * @param fmtArg Control string. * @exception IllegalArgumentException if the control * string is null, zero length, or otherwise * malformed. */ public PrintfFormat(Locale locale, String fmtArg) throws IllegalArgumentException { dfs = new DecimalFormatSymbols(locale); int ePos = 0; ConversionSpecification sFmt = null; String unCS = this.nonControl(fmtArg, 0); if (unCS != null) { sFmt = new ConversionSpecification(); sFmt.setLiteral(unCS); vFmt.addElement(sFmt); } while (cPos != -1 && cPos < fmtArg.length()) { for (ePos = cPos + 1; ePos < fmtArg.length(); ePos++) { char c = 0; c = fmtArg.charAt(ePos); if (c == 'i') break; if (c == 'd') break; if (c == 'f') break; if (c == 'g') break; if (c == 'G') break; if (c == 'o') break; if (c == 'x') break; if (c == 'X') break; if (c == 'e') break; if (c == 'E') break; if (c == 'c') break; if (c == 's') break; if (c == '%') break; } ePos = Math.min(ePos + 1, fmtArg.length()); sFmt = new ConversionSpecification(fmtArg.substring(cPos, ePos)); vFmt.addElement(sFmt); unCS = this.nonControl(fmtArg, ePos); if (unCS != null) { sFmt = new ConversionSpecification(); sFmt.setLiteral(unCS); vFmt.addElement(sFmt); } } } /** * Return a substring starting at * <code>start</code> and ending at either the end * of the String <code>s</code>, the next unpaired * percent sign, or at the end of the String if the * last character is a percent sign. * @param s Control string. * @param start Position in the string * <code>s</code> to begin looking for the start * of a control string. * @return the substring from the start position * to the beginning of the control string. */ private String nonControl(String s, int start) { String ret = ""; cPos = s.indexOf("%", start); if (cPos == -1) cPos = s.length(); return s.substring(start, cPos); } /** * Format an array of objects. Byte, Short, * Integer, Long, Float, Double, and Character * arguments are treated as wrappers for primitive * types. * @param o The array of objects to format. * @return The formatted String. */ public String sprintf(Object[] o) { Enumeration e = vFmt.elements(); ConversionSpecification cs = null; char c = 0; int i = 0; StringBuffer sb = new StringBuffer(); while (e.hasMoreElements()) { cs = (ConversionSpecification) e.nextElement(); c = cs.getConversionCharacter(); if (c == '\0') sb.append(cs.getLiteral()); else if (c == '%') sb.append("%"); else { if (cs.isPositionalSpecification()) { i = cs.getArgumentPosition() - 1; if (cs.isPositionalFieldWidth()) { int ifw = cs.getArgumentPositionForFieldWidth() - 1; cs.setFieldWidthWithArg(((Integer) o[ifw]).intValue()); } if (cs.isPositionalPrecision()) { int ipr = cs.getArgumentPositionForPrecision() - 1; cs.setPrecisionWithArg(((Integer) o[ipr]).intValue()); } } else { if (cs.isVariableFieldWidth()) { cs.setFieldWidthWithArg(((Integer) o[i]).intValue()); i++; } if (cs.isVariablePrecision()) { cs.setPrecisionWithArg(((Integer) o[i]).intValue()); i++; } } if (o[i] instanceof Byte) sb.append(cs.internalsprintf(((Byte) o[i]).byteValue())); else if (o[i] instanceof Short) sb.append(cs.internalsprintf(((Short) o[i]).shortValue())); else if (o[i] instanceof Integer) sb.append(cs.internalsprintf(((Integer) o[i]).intValue())); else if (o[i] instanceof Long) sb.append(cs.internalsprintf(((Long) o[i]).longValue())); else if (o[i] instanceof Float) sb.append(cs.internalsprintf(((Float) o[i]).floatValue())); else if (o[i] instanceof Double) sb.append(cs.internalsprintf(((Double) o[i]).doubleValue())); else if (o[i] instanceof Character) sb.append(cs.internalsprintf(((Character) o[i]).charValue())); else if (o[i] instanceof String) sb.append(cs.internalsprintf((String) o[i])); else sb.append(cs.internalsprintf(o[i])); if (!cs.isPositionalSpecification()) i++; } } return sb.toString(); } /** * Format nothing. Just use the control string. * @return the formatted String. */ public String sprintf() { Enumeration e = vFmt.elements(); ConversionSpecification cs = null; char c = 0; StringBuffer sb = new StringBuffer(); while (e.hasMoreElements()) { cs = (ConversionSpecification) e.nextElement(); c = cs.getConversionCharacter(); if (c == '\0') sb.append(cs.getLiteral()); else if (c == '%') sb.append("%"); } return sb.toString(); } /** * Format an int. * @param x The int to format. * @return The formatted String. * @exception IllegalArgumentException if the * conversion character is f, e, E, g, G, s, * or S. */ public String sprintf(int x) throws IllegalArgumentException { Enumeration e = vFmt.elements(); ConversionSpecification cs = null; char c = 0; StringBuffer sb = new StringBuffer(); while (e.hasMoreElements()) { cs = (ConversionSpecification) e.nextElement(); c = cs.getConversionCharacter(); if (c == '\0') sb.append(cs.getLiteral()); else if (c == '%') sb.append("%"); else sb.append(cs.internalsprintf(x)); } return sb.toString(); } /** * Format an long. * @param x The long to format. * @return The formatted String. * @exception IllegalArgumentException if the * conversion character is f, e, E, g, G, s, * or S. */ public String sprintf(long x) throws IllegalArgumentException { Enumeration e = vFmt.elements(); ConversionSpecification cs = null; char c = 0; StringBuffer sb = new StringBuffer(); while (e.hasMoreElements()) { cs = (ConversionSpecification) e.nextElement(); c = cs.getConversionCharacter(); if (c == '\0') sb.append(cs.getLiteral()); else if (c == '%') sb.append("%"); else sb.append(cs.internalsprintf(x)); } return sb.toString(); } /** * Format a double. * @param x The double to format. * @return The formatted String. * @exception IllegalArgumentException if the * conversion character is c, C, s, S, * d, d, x, X, or o. */ public String sprintf(double x) throws IllegalArgumentException { Enumeration e = vFmt.elements(); ConversionSpecification cs = null; char c = 0; StringBuffer sb = new StringBuffer(); while (e.hasMoreElements()) { cs = (ConversionSpecification) e.nextElement(); c = cs.getConversionCharacter(); if (c == '\0') sb.append(cs.getLiteral()); else if (c == '%') sb.append("%"); else sb.append(cs.internalsprintf(x)); } return sb.toString(); } /** * Format a String. * @param x The String to format. * @return The formatted String. * @exception IllegalArgumentException if the * conversion character is neither s nor S. */ public String sprintf(String x) throws IllegalArgumentException { Enumeration e = vFmt.elements(); ConversionSpecification cs = null; char c = 0; StringBuffer sb = new StringBuffer(); while (e.hasMoreElements()) { cs = (ConversionSpecification) e.nextElement(); c = cs.getConversionCharacter(); if (c == '\0') sb.append(cs.getLiteral()); else if (c == '%') sb.append("%"); else sb.append(cs.internalsprintf(x)); } return sb.toString(); } /** * Format an Object. Convert wrapper types to * their primitive equivalents and call the * appropriate internal formatting method. Convert * Strings using an internal formatting method for * Strings. Otherwise use the default formatter * (use toString). * @param x the Object to format. * @return the formatted String. * @exception IllegalArgumentException if the * conversion character is inappropriate for * formatting an unwrapped value. */ public String sprintf(Object x) throws IllegalArgumentException { Enumeration e = vFmt.elements(); ConversionSpecification cs = null; char c = 0; StringBuffer sb = new StringBuffer(); while (e.hasMoreElements()) { cs = (ConversionSpecification) e.nextElement(); c = cs.getConversionCharacter(); if (c == '\0') sb.append(cs.getLiteral()); else if (c == '%') sb.append("%"); else { if (x instanceof Byte) sb.append(cs.internalsprintf(((Byte) x).byteValue())); else if (x instanceof Short) sb.append(cs.internalsprintf(((Short) x).shortValue())); else if (x instanceof Integer) sb.append(cs.internalsprintf(((Integer) x).intValue())); else if (x instanceof Long) sb.append(cs.internalsprintf(((Long) x).longValue())); else if (x instanceof Float) sb.append(cs.internalsprintf(((Float) x).floatValue())); else if (x instanceof Double) sb.append(cs.internalsprintf(((Double) x).doubleValue())); else if (x instanceof Character) sb.append(cs.internalsprintf(((Character) x).charValue())); else if (x instanceof String) sb.append(cs.internalsprintf((String) x)); else sb.append(cs.internalsprintf(x)); } } return sb.toString(); } /** *<p> * ConversionSpecification allows the formatting of * a single primitive or object embedded within a * string. The formatting is controlled by a * format string. Only one Java primitive or * object can be formatted at a time. *<p> * A format string is a Java string that contains * a control string. The control string starts at * the first percent sign (%) in the string, * provided that this percent sign *<ol> *<li>is not escaped protected by a matching % or * is not an escape % character, *<li>is not at the end of the format string, and *<li>precedes a sequence of characters that parses * as a valid control string. *</ol> *<p> * A control string takes the form: *<pre> % ['-+ #0]* [0..9]* { . [0..9]* }+ * { [hlL] }+ [idfgGoxXeEcs] *</pre> *<p> * The behavior is like printf. One (hopefully the * only) exception is that the minimum number of * exponent digits is 3 instead of 2 for e and E * formats when the optional L is used before the * e, E, g, or G conversion character. The * optional L does not imply conversion to a long * long double. */ private class ConversionSpecification { /** * Constructor. Used to prepare an instance * to hold a literal, not a control string. */ ConversionSpecification() { } /** * Constructor for a conversion specification. * The argument must begin with a % and end * with the conversion character for the * conversion specification. * @param fmtArg String specifying the * conversion specification. * @exception IllegalArgumentException if the * input string is null, zero length, or * otherwise malformed. */ ConversionSpecification(String fmtArg) throws IllegalArgumentException { if (fmtArg == null) throw new NullPointerException(); if (fmtArg.length() == 0) throw new IllegalArgumentException("Control strings must have positive" + " lengths."); if (fmtArg.charAt(0) == '%') { fmt = fmtArg; pos = 1; setArgPosition(); setFlagCharacters(); setFieldWidth(); setPrecision(); setOptionalHL(); if (setConversionCharacter()) { if (pos == fmtArg.length()) { if (leadingZeros && leftJustify) leadingZeros = false; if (precisionSet && leadingZeros) { if (conversionCharacter == 'd' || conversionCharacter == 'i' || conversionCharacter == 'o' || conversionCharacter == 'x') { leadingZeros = false; } } } else throw new IllegalArgumentException("Malformed conversion specification=" + fmtArg); } else throw new IllegalArgumentException("Malformed conversion specification=" + fmtArg); } else throw new IllegalArgumentException("Control strings must begin with %."); } /** * Set the String for this instance. * @param s the String to store. */ void setLiteral(String s) { fmt = s;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -