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 +     * Returns a charset object for the given charset name.
     1856 +     * @throws NullPointerException          is csn is null
     1857 +     * @throws UnsupportedEncodingException  if the charset is not supported
     1858 +     */
     1859 +    private static Charset toCharset(String csn)
     1860 +            throws UnsupportedEncodingException {
     1861 +        Objects.nonNull(csn, "charsetName");
     1862 +        try {
     1863 +            return Charset.forName(csn);
     1864 +        } catch (IllegalCharsetNameException unused) {
     1865 +            /* swallow this exception since UnsupportedEncodingException
     1866 +             * will be thrown */
     1867 +        }
     1868 +        throw new UnsupportedEncodingException(csn);
     1869 +    }
     1870 +
     1871 +    private static final Appendable nonNullAppendable(Appendable a) {
     1872 +        if (a == null)
     1873 +            return new StringBuilder();
     1874 +
     1875 +        return a;
     1876 +    }
     1877 +
     1878 +    /* Private constructors */
     1879 +    private Formatter(Locale l, Appendable a) {
1854 1880          this.a = a;
1855 1881          this.l = l;
1856      -        setZero();
     1882 +        this.zero = getZero(l);
1857 1883      }
1858 1884  
     1885 +    private Formatter(Charset charset, Locale l, File file)
     1886 +            throws FileNotFoundException {
     1887 +        this(l,
     1888 +             new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)));
     1889 +    }
     1890 +
1859 1891      /**
1860 1892       * Constructs a new formatter.
1861 1893       *
1862 1894       * <p> The destination of the formatted output is a {@link StringBuilder}
1863 1895       * which may be retrieved by invoking {@link #out out()} and whose
1864 1896       * current content may be converted into a string by invoking {@link
1865 1897       * #toString toString()}.  The locale used is the {@linkplain
1866 1898       * Locale#getDefault() default locale} for this instance of the Java
1867 1899       * virtual machine.
1868 1900       */
1869 1901      public Formatter() {
1870      -        init(new StringBuilder(), Locale.getDefault(Locale.Category.FORMAT));
     1902 +        this(Locale.getDefault(Locale.Category.FORMAT), new StringBuilder());
1871 1903      }
1872 1904  
1873 1905      /**
1874 1906       * Constructs a new formatter with the specified destination.
1875 1907       *
1876 1908       * <p> The locale used is the {@linkplain Locale#getDefault() default
1877 1909       * locale} for this instance of the Java virtual machine.
1878 1910       *
1879 1911       * @param  a
1880 1912       *         Destination for the formatted output.  If {@code a} is
1881 1913       *         {@code null} then a {@link StringBuilder} will be created.
1882 1914       */
1883 1915      public Formatter(Appendable a) {
1884      -        if (a == null)
1885      -            a = new StringBuilder();
1886      -        init(a, Locale.getDefault(Locale.Category.FORMAT));
     1916 +        this(Locale.getDefault(Locale.Category.FORMAT), nonNullAppendable(a));
1887 1917      }
1888 1918  
1889 1919      /**
1890 1920       * Constructs a new formatter with the specified locale.
1891 1921       *
1892 1922       * <p> The destination of the formatted output is a {@link StringBuilder}
1893 1923       * which may be retrieved by invoking {@link #out out()} and whose current
1894 1924       * content may be converted into a string by invoking {@link #toString
1895 1925       * toString()}.
1896 1926       *
1897 1927       * @param  l
1898 1928       *         The {@linkplain java.util.Locale locale} to apply during
1899 1929       *         formatting.  If {@code l} is {@code null} then no localization
1900 1930       *         is applied.
1901 1931       */
1902 1932      public Formatter(Locale l) {
1903      -        init(new StringBuilder(), l);
     1933 +        this(l, new StringBuilder());
1904 1934      }
1905 1935  
1906 1936      /**
1907 1937       * Constructs a new formatter with the specified destination and locale.
1908 1938       *
1909 1939       * @param  a
1910 1940       *         Destination for the formatted output.  If {@code a} is
1911 1941       *         {@code null} then a {@link StringBuilder} will be created.
1912 1942       *
1913 1943       * @param  l
1914 1944       *         The {@linkplain java.util.Locale locale} to apply during
1915 1945       *         formatting.  If {@code l} is {@code null} then no localization
1916 1946       *         is applied.
1917 1947       */
1918 1948      public Formatter(Appendable a, Locale l) {
1919      -        if (a == null)
1920      -            a = new StringBuilder();
1921      -        init(a, l);
     1949 +        this(l, nonNullAppendable(a));
1922 1950      }
1923 1951  
1924 1952      /**
1925 1953       * Constructs a new formatter with the specified file name.
1926 1954       *
1927 1955       * <p> The charset used is the {@linkplain
1928 1956       * java.nio.charset.Charset#defaultCharset() default charset} for this
1929 1957       * instance of the Java virtual machine.
1930 1958       *
1931 1959       * <p> The locale used is the {@linkplain Locale#getDefault() default
↓ open down ↓ 10 lines elided ↑ open up ↑
1942 1970       *          SecurityManager#checkWrite checkWrite(fileName)} denies write
1943 1971       *          access to the file
1944 1972       *
1945 1973       * @throws  FileNotFoundException
1946 1974       *          If the given file name does not denote an existing, writable
1947 1975       *          regular file and a new regular file of that name cannot be
1948 1976       *          created, or if some other error occurs while opening or
1949 1977       *          creating the file
1950 1978       */
1951 1979      public Formatter(String fileName) throws FileNotFoundException {
1952      -        init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),
1953      -             Locale.getDefault(Locale.Category.FORMAT));
     1980 +        this(Locale.getDefault(Locale.Category.FORMAT),
     1981 +             new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))));
1954 1982      }
1955 1983  
1956 1984      /**
1957 1985       * Constructs a new formatter with the specified file name and charset.
1958 1986       *
1959 1987       * <p> The locale used is the {@linkplain Locale#getDefault default
1960 1988       * locale} for this instance of the Java virtual machine.
1961 1989       *
1962 1990       * @param  fileName
1963 1991       *         The name of the file to use as the destination of this
↓ open down ↓ 54 lines elided ↑ open up ↑
2018 2046       *          If a security manager is present and {@link
2019 2047       *          SecurityManager#checkWrite checkWrite(fileName)} denies write
2020 2048       *          access to the file
2021 2049       *
2022 2050       * @throws  UnsupportedEncodingException
2023 2051       *          If the named charset is not supported
2024 2052       */
2025 2053      public Formatter(String fileName, String csn, Locale l)
2026 2054          throws FileNotFoundException, UnsupportedEncodingException
2027 2055      {
2028      -        init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), csn)),
2029      -             l);
     2056 +        this(toCharset(csn), l, new File(fileName));
2030 2057      }
2031 2058  
2032 2059      /**
2033 2060       * Constructs a new formatter with the specified file.
2034 2061       *
2035 2062       * <p> The charset used is the {@linkplain
2036 2063       * java.nio.charset.Charset#defaultCharset() default charset} for this
2037 2064       * instance of the Java virtual machine.
2038 2065       *
2039 2066       * <p> The locale used is the {@linkplain Locale#getDefault() default
↓ open down ↓ 10 lines elided ↑ open up ↑
2050 2077       *          SecurityManager#checkWrite checkWrite(file.getPath())} denies
2051 2078       *          write access to the file
2052 2079       *
2053 2080       * @throws  FileNotFoundException
2054 2081       *          If the given file object does not denote an existing, writable
2055 2082       *          regular file and a new regular file of that name cannot be
2056 2083       *          created, or if some other error occurs while opening or
2057 2084       *          creating the file
2058 2085       */
2059 2086      public Formatter(File file) throws FileNotFoundException {
2060      -        init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),
2061      -             Locale.getDefault(Locale.Category.FORMAT));
     2087 +        this(Locale.getDefault(Locale.Category.FORMAT),
     2088 +             new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))));
2062 2089      }
2063 2090  
2064 2091      /**
2065 2092       * Constructs a new formatter with the specified file and charset.
2066 2093       *
2067 2094       * <p> The locale used is the {@linkplain Locale#getDefault default
2068 2095       * locale} for this instance of the Java virtual machine.
2069 2096       *
2070 2097       * @param  file
2071 2098       *         The file to use as the destination of this formatter.  If the
↓ open down ↓ 54 lines elided ↑ open up ↑
2126 2153       *          If a security manager is present and {@link
2127 2154       *          SecurityManager#checkWrite checkWrite(file.getPath())} denies
2128 2155       *          write access to the file
2129 2156       *
2130 2157       * @throws  UnsupportedEncodingException
2131 2158       *          If the named charset is not supported
2132 2159       */
2133 2160      public Formatter(File file, String csn, Locale l)
2134 2161          throws FileNotFoundException, UnsupportedEncodingException
2135 2162      {
2136      -        init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), csn)),
2137      -             l);
     2163 +        this(toCharset(csn), l, file);
2138 2164      }
2139 2165  
2140 2166      /**
2141 2167       * Constructs a new formatter with the specified print stream.
2142 2168       *
2143 2169       * <p> The locale used is the {@linkplain Locale#getDefault() default
2144 2170       * locale} for this instance of the Java virtual machine.
2145 2171       *
2146 2172       * <p> Characters are written to the given {@link java.io.PrintStream
2147 2173       * PrintStream} object and are therefore encoded using that object's
2148 2174       * charset.
2149 2175       *
2150 2176       * @param  ps
2151 2177       *         The stream to use as the destination of this formatter.
2152 2178       */
2153 2179      public Formatter(PrintStream ps) {
2154      -        if (ps == null)
2155      -            throw new NullPointerException();
2156      -        init((Appendable)ps, Locale.getDefault(Locale.Category.FORMAT));
     2180 +        this(Locale.getDefault(Locale.Category.FORMAT),
     2181 +             (Appendable)Objects.nonNull(ps));
2157 2182      }
2158 2183  
2159 2184      /**
2160 2185       * Constructs a new formatter with the specified output stream.
2161 2186       *
2162 2187       * <p> The charset used is the {@linkplain
2163 2188       * java.nio.charset.Charset#defaultCharset() default charset} for this
2164 2189       * instance of the Java virtual machine.
2165 2190       *
2166 2191       * <p> The locale used is the {@linkplain Locale#getDefault() default
2167 2192       * locale} for this instance of the Java virtual machine.
2168 2193       *
2169 2194       * @param  os
2170 2195       *         The output stream to use as the destination of this formatter.
2171 2196       *         The output will be buffered.
2172 2197       */
2173 2198      public Formatter(OutputStream os) {
2174      -        init(new BufferedWriter(new OutputStreamWriter(os)),
2175      -             Locale.getDefault(Locale.Category.FORMAT));
     2199 +        this(Locale.getDefault(Locale.Category.FORMAT),
     2200 +             new BufferedWriter(new OutputStreamWriter(os)));
2176 2201      }
2177 2202  
2178 2203      /**
2179 2204       * Constructs a new formatter with the specified output stream and
2180 2205       * charset.
2181 2206       *
2182 2207       * <p> The locale used is the {@linkplain Locale#getDefault default
2183 2208       * locale} for this instance of the Java virtual machine.
2184 2209       *
2185 2210       * @param  os
↓ open down ↓ 29 lines elided ↑ open up ↑
2215 2240       *         The {@linkplain java.util.Locale locale} to apply during
2216 2241       *         formatting.  If {@code l} is {@code null} then no localization
2217 2242       *         is applied.
2218 2243       *
2219 2244       * @throws  UnsupportedEncodingException
2220 2245       *          If the named charset is not supported
2221 2246       */
2222 2247      public Formatter(OutputStream os, String csn, Locale l)
2223 2248          throws UnsupportedEncodingException
2224 2249      {
2225      -        init(new BufferedWriter(new OutputStreamWriter(os, csn)), l);
     2250 +        this(l, new BufferedWriter(new OutputStreamWriter(os, csn)));
2226 2251      }
2227 2252  
2228      -    private void setZero() {
     2253 +    private static final char getZero(Locale l) {
2229 2254          if ((l != null) && !l.equals(Locale.US)) {
2230 2255              DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
2231      -            zero = dfs.getZeroDigit();
     2256 +            return dfs.getZeroDigit();
     2257 +        } else {
     2258 +            return '0';
2232 2259          }
2233 2260      }
2234 2261  
2235 2262      /**
2236 2263       * Returns the locale set by the construction of this formatter.
2237 2264       *
2238 2265       * <p> The {@link #format(java.util.Locale,String,Object...) format} method
2239 2266       * for this object which has a locale argument does not change this value.
2240 2267       *
2241 2268       * @return  {@code null} if no localization is applied, otherwise a
↓ open down ↓ 2179 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX