Print this page


Split Close
Expand all
Collapse all
          --- old/src/share/classes/java/util/Formatter.java
          +++ new/src/share/classes/java/util/Formatter.java
↓ open down ↓ 42 lines elided ↑ open up ↑
  43   43  import java.nio.charset.Charset;
  44   44  import java.text.DateFormatSymbols;
  45   45  import java.text.DecimalFormat;
  46   46  import java.text.DecimalFormatSymbols;
  47   47  import java.text.NumberFormat;
  48   48  import java.util.Calendar;
  49   49  import java.util.Date;
  50   50  import java.util.Locale;
  51   51  import java.util.regex.Matcher;
  52   52  import java.util.regex.Pattern;
       53 +import java.nio.charset.Charset;
       54 +import java.nio.charset.IllegalCharsetNameException;
  53   55  
  54   56  import sun.misc.FpUtils;
  55   57  import sun.misc.DoubleConsts;
  56   58  import sun.misc.FormattedFloatingDecimal;
  57   59  
  58   60  /**
  59   61   * An interpreter for printf-style format strings.  This class provides support
  60   62   * for layout justification and alignment, common formats for numeric, string,
  61   63   * and date/time data, and locale-specific output.  Common Java types such as
  62   64   * {@code byte}, {@link java.math.BigDecimal BigDecimal}, and {@link Calendar}
↓ open down ↓ 1768 lines elided ↑ open up ↑
1831 1833   *
1832 1834   * <p> Unless otherwise specified, passing a {@code null} argument to any
1833 1835   * method or constructor in this class will cause a {@link
1834 1836   * NullPointerException} to be thrown.
1835 1837   *
1836 1838   * @author  Iris Clark
1837 1839   * @since 1.5
1838 1840   */
1839 1841  public final class Formatter implements Closeable, Flushable {
1840 1842      private Appendable a;
1841      -    private Locale l;
     1843 +    private final Locale l;
1842 1844  
1843 1845      private IOException lastException;
1844 1846  
1845      -    private char zero = '0';
     1847 +    private final char zero;
1846 1848      private static double scaleUp;
1847 1849  
1848 1850      // 1 (sign) + 19 (max # sig digits) + 1 ('.') + 1 ('e') + 1 (sign)
1849 1851      // + 3 (max # exp digits) + 4 (error) = 30
1850 1852      private static final int MAX_FD_CHARS = 30;
1851 1853  
1852      -    // Initialize internal data.
1853      -    private void init(Appendable a, Locale l) {
     1854 +    /**
     1855 +     * Verifies that the given charset is supported.
     1856 +     * @throws NullPointerException          is csn is null
     1857 +     * @throws UnsupportedEncodingException  if the charset is not supported
     1858 +     */
     1859 +    private static Void verifyCharsetName(String csn)
     1860 +            throws UnsupportedEncodingException {
     1861 +        Objects.nonNull(csn, "charsetName");
     1862 +        try {
     1863 +            if (Charset.isSupported(csn))
     1864 +                return null;
     1865 +        } catch (IllegalCharsetNameException unused) {
     1866 +            /* swallow this exception since UnsupportedEncodingException
     1867 +             * will be thrown */
     1868 +        }
     1869 +        throw new UnsupportedEncodingException(csn);
     1870 +    }
     1871 +
     1872 +    private static final Appendable nonNullAppendable(Appendable a) {
     1873 +        if (a == null)
     1874 +            return new StringBuilder();
     1875 +
     1876 +        return a;
     1877 +    }
     1878 +
     1879 +    // Private constructors
     1880 +    private Formatter(Void unused, Locale l, Appendable a) {
     1881 +        this(l, a);
     1882 +    }
     1883 +
     1884 +    private Formatter(Locale l, Appendable a) {
1854 1885          this.a = a;
1855 1886          this.l = l;
1856      -        setZero();
     1887 +        this.zero = getZero(l);
1857 1888      }
1858 1889  
1859 1890      /**
1860 1891       * Constructs a new formatter.
1861 1892       *
1862 1893       * <p> The destination of the formatted output is a {@link StringBuilder}
1863 1894       * which may be retrieved by invoking {@link #out out()} and whose
1864 1895       * current content may be converted into a string by invoking {@link
1865 1896       * #toString toString()}.  The locale used is the {@linkplain
1866 1897       * Locale#getDefault() default locale} for this instance of the Java
1867 1898       * virtual machine.
1868 1899       */
1869 1900      public Formatter() {
1870      -        init(new StringBuilder(), Locale.getDefault(Locale.Category.FORMAT));
     1901 +        this(Locale.getDefault(Locale.Category.FORMAT), new StringBuilder());
1871 1902      }
1872 1903  
1873 1904      /**
1874 1905       * Constructs a new formatter with the specified destination.
1875 1906       *
1876 1907       * <p> The locale used is the {@linkplain Locale#getDefault() default
1877 1908       * locale} for this instance of the Java virtual machine.
1878 1909       *
1879 1910       * @param  a
1880 1911       *         Destination for the formatted output.  If {@code a} is
1881 1912       *         {@code null} then a {@link StringBuilder} will be created.
1882 1913       */
1883 1914      public Formatter(Appendable a) {
1884      -        if (a == null)
1885      -            a = new StringBuilder();
1886      -        init(a, Locale.getDefault(Locale.Category.FORMAT));
     1915 +        this(Locale.getDefault(Locale.Category.FORMAT), nonNullAppendable(a));
1887 1916      }
1888 1917  
1889 1918      /**
1890 1919       * Constructs a new formatter with the specified locale.
1891 1920       *
1892 1921       * <p> The destination of the formatted output is a {@link StringBuilder}
1893 1922       * which may be retrieved by invoking {@link #out out()} and whose current
1894 1923       * content may be converted into a string by invoking {@link #toString
1895 1924       * toString()}.
1896 1925       *
1897 1926       * @param  l
1898 1927       *         The {@linkplain java.util.Locale locale} to apply during
1899 1928       *         formatting.  If {@code l} is {@code null} then no localization
1900 1929       *         is applied.
1901 1930       */
1902 1931      public Formatter(Locale l) {
1903      -        init(new StringBuilder(), l);
     1932 +        this(l, new StringBuilder());
1904 1933      }
1905 1934  
1906 1935      /**
1907 1936       * Constructs a new formatter with the specified destination and locale.
1908 1937       *
1909 1938       * @param  a
1910 1939       *         Destination for the formatted output.  If {@code a} is
1911 1940       *         {@code null} then a {@link StringBuilder} will be created.
1912 1941       *
1913 1942       * @param  l
1914 1943       *         The {@linkplain java.util.Locale locale} to apply during
1915 1944       *         formatting.  If {@code l} is {@code null} then no localization
1916 1945       *         is applied.
1917 1946       */
1918 1947      public Formatter(Appendable a, Locale l) {
1919      -        if (a == null)
1920      -            a = new StringBuilder();
1921      -        init(a, l);
     1948 +        this(l, nonNullAppendable(a));
1922 1949      }
1923 1950  
1924 1951      /**
1925 1952       * Constructs a new formatter with the specified file name.
1926 1953       *
1927 1954       * <p> The charset used is the {@linkplain
1928 1955       * java.nio.charset.Charset#defaultCharset() default charset} for this
1929 1956       * instance of the Java virtual machine.
1930 1957       *
1931 1958       * <p> The locale used is the {@linkplain Locale#getDefault() default
↓ open down ↓ 10 lines elided ↑ open up ↑
1942 1969       *          SecurityManager#checkWrite checkWrite(fileName)} denies write
1943 1970       *          access to the file
1944 1971       *
1945 1972       * @throws  FileNotFoundException
1946 1973       *          If the given file name does not denote an existing, writable
1947 1974       *          regular file and a new regular file of that name cannot be
1948 1975       *          created, or if some other error occurs while opening or
1949 1976       *          creating the file
1950 1977       */
1951 1978      public Formatter(String fileName) throws FileNotFoundException {
1952      -        init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),
1953      -             Locale.getDefault(Locale.Category.FORMAT));
     1979 +        this(Locale.getDefault(Locale.Category.FORMAT),
     1980 +             new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))));
1954 1981      }
1955 1982  
1956 1983      /**
1957 1984       * Constructs a new formatter with the specified file name and charset.
1958 1985       *
1959 1986       * <p> The locale used is the {@linkplain Locale#getDefault default
1960 1987       * locale} for this instance of the Java virtual machine.
1961 1988       *
1962 1989       * @param  fileName
1963 1990       *         The name of the file to use as the destination of this
↓ open down ↓ 54 lines elided ↑ open up ↑
2018 2045       *          If a security manager is present and {@link
2019 2046       *          SecurityManager#checkWrite checkWrite(fileName)} denies write
2020 2047       *          access to the file
2021 2048       *
2022 2049       * @throws  UnsupportedEncodingException
2023 2050       *          If the named charset is not supported
2024 2051       */
2025 2052      public Formatter(String fileName, String csn, Locale l)
2026 2053          throws FileNotFoundException, UnsupportedEncodingException
2027 2054      {
2028      -        init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), csn)),
2029      -             l);
     2055 +        this(verifyCharsetName(csn),
     2056 +             l,
     2057 +             new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), csn)));
2030 2058      }
2031 2059  
2032 2060      /**
2033 2061       * Constructs a new formatter with the specified file.
2034 2062       *
2035 2063       * <p> The charset used is the {@linkplain
2036 2064       * java.nio.charset.Charset#defaultCharset() default charset} for this
2037 2065       * instance of the Java virtual machine.
2038 2066       *
2039 2067       * <p> The locale used is the {@linkplain Locale#getDefault() default
↓ open down ↓ 10 lines elided ↑ open up ↑
2050 2078       *          SecurityManager#checkWrite checkWrite(file.getPath())} denies
2051 2079       *          write access to the file
2052 2080       *
2053 2081       * @throws  FileNotFoundException
2054 2082       *          If the given file object does not denote an existing, writable
2055 2083       *          regular file and a new regular file of that name cannot be
2056 2084       *          created, or if some other error occurs while opening or
2057 2085       *          creating the file
2058 2086       */
2059 2087      public Formatter(File file) throws FileNotFoundException {
2060      -        init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),
2061      -             Locale.getDefault(Locale.Category.FORMAT));
     2088 +        this(Locale.getDefault(Locale.Category.FORMAT),
     2089 +             new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))));
2062 2090      }
2063 2091  
2064 2092      /**
2065 2093       * Constructs a new formatter with the specified file and charset.
2066 2094       *
2067 2095       * <p> The locale used is the {@linkplain Locale#getDefault default
2068 2096       * locale} for this instance of the Java virtual machine.
2069 2097       *
2070 2098       * @param  file
2071 2099       *         The file to use as the destination of this formatter.  If the
↓ open down ↓ 54 lines elided ↑ open up ↑
2126 2154       *          If a security manager is present and {@link
2127 2155       *          SecurityManager#checkWrite checkWrite(file.getPath())} denies
2128 2156       *          write access to the file
2129 2157       *
2130 2158       * @throws  UnsupportedEncodingException
2131 2159       *          If the named charset is not supported
2132 2160       */
2133 2161      public Formatter(File file, String csn, Locale l)
2134 2162          throws FileNotFoundException, UnsupportedEncodingException
2135 2163      {
2136      -        init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), csn)),
2137      -             l);
     2164 +        this(verifyCharsetName(csn),
     2165 +             l,
     2166 +             new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), csn)));
2138 2167      }
2139 2168  
2140 2169      /**
2141 2170       * Constructs a new formatter with the specified print stream.
2142 2171       *
2143 2172       * <p> The locale used is the {@linkplain Locale#getDefault() default
2144 2173       * locale} for this instance of the Java virtual machine.
2145 2174       *
2146 2175       * <p> Characters are written to the given {@link java.io.PrintStream
2147 2176       * PrintStream} object and are therefore encoded using that object's
2148 2177       * charset.
2149 2178       *
2150 2179       * @param  ps
2151 2180       *         The stream to use as the destination of this formatter.
2152 2181       */
2153 2182      public Formatter(PrintStream ps) {
2154      -        if (ps == null)
2155      -            throw new NullPointerException();
2156      -        init((Appendable)ps, Locale.getDefault(Locale.Category.FORMAT));
     2183 +        this(Locale.getDefault(Locale.Category.FORMAT),
     2184 +             (Appendable)Objects.nonNull(ps));
2157 2185      }
2158 2186  
2159 2187      /**
2160 2188       * Constructs a new formatter with the specified output stream.
2161 2189       *
2162 2190       * <p> The charset used is the {@linkplain
2163 2191       * java.nio.charset.Charset#defaultCharset() default charset} for this
2164 2192       * instance of the Java virtual machine.
2165 2193       *
2166 2194       * <p> The locale used is the {@linkplain Locale#getDefault() default
2167 2195       * locale} for this instance of the Java virtual machine.
2168 2196       *
2169 2197       * @param  os
2170 2198       *         The output stream to use as the destination of this formatter.
2171 2199       *         The output will be buffered.
2172 2200       */
2173 2201      public Formatter(OutputStream os) {
2174      -        init(new BufferedWriter(new OutputStreamWriter(os)),
2175      -             Locale.getDefault(Locale.Category.FORMAT));
     2202 +        this(Locale.getDefault(Locale.Category.FORMAT),
     2203 +             new BufferedWriter(new OutputStreamWriter(os)));
2176 2204      }
2177 2205  
2178 2206      /**
2179 2207       * Constructs a new formatter with the specified output stream and
2180 2208       * charset.
2181 2209       *
2182 2210       * <p> The locale used is the {@linkplain Locale#getDefault default
2183 2211       * locale} for this instance of the Java virtual machine.
2184 2212       *
2185 2213       * @param  os
↓ open down ↓ 29 lines elided ↑ open up ↑
2215 2243       *         The {@linkplain java.util.Locale locale} to apply during
2216 2244       *         formatting.  If {@code l} is {@code null} then no localization
2217 2245       *         is applied.
2218 2246       *
2219 2247       * @throws  UnsupportedEncodingException
2220 2248       *          If the named charset is not supported
2221 2249       */
2222 2250      public Formatter(OutputStream os, String csn, Locale l)
2223 2251          throws UnsupportedEncodingException
2224 2252      {
2225      -        init(new BufferedWriter(new OutputStreamWriter(os, csn)), l);
     2253 +        this(l, new BufferedWriter(new OutputStreamWriter(os, csn)));
2226 2254      }
2227 2255  
2228      -    private void setZero() {
     2256 +    private static final char getZero(Locale l) {
2229 2257          if ((l != null) && !l.equals(Locale.US)) {
2230 2258              DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
2231      -            zero = dfs.getZeroDigit();
     2259 +            return dfs.getZeroDigit();
     2260 +        } else {
     2261 +            return '0';
2232 2262          }
2233 2263      }
2234 2264  
2235 2265      /**
2236 2266       * Returns the locale set by the construction of this formatter.
2237 2267       *
2238 2268       * <p> The {@link #format(java.util.Locale,String,Object...) format} method
2239 2269       * for this object which has a locale argument does not change this value.
2240 2270       *
2241 2271       * @return  {@code null} if no localization is applied, otherwise a
↓ open down ↓ 2179 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX