Skip to main content
  1. Java NIO (New I/O)/

Charset

2 mins

The Charset class represents a character encoding scheme that maps between sequences of sixteen-bit Unicode code units and sequences of bytes. It provides methods for creating encoders and decoders, retrieving charset names, and discovering available charsets.

Source Code #

View Source on GitHub

Core Implementation #

public abstract class Charset implements Comparable<Charset> {
    private final String name;          // Canonical charset name
    private final String[] aliases;     // Charset aliases
    private final Set<String> aliasSet; // Immutable alias set
    
    protected Charset(String canonicalName, String[] aliases) {
        // Validate charset name
        checkName(canonicalName);
        for (String alias : aliases) {
            checkName(alias);
        }
        
        this.name = canonicalName;
        this.aliases = aliases.clone();
        
        // Create immutable alias set
        Set<String> hs = new HashSet<>();
        for (String alias : aliases) {
            hs.add(alias);
        }
        hs.add(canonicalName);
        this.aliasSet = Collections.unmodifiableSet(hs);
    }
    
    public final String name() {
        return name;
    }
    
    public final Set<String> aliases() {
        return aliasSet;
    }
    
    public String displayName() {
        return name;
    }
    
    public String displayName(Locale locale) {
        return name;
    }
    
    public final boolean isRegistered() {
        return !name.startsWith("X-") && !name.startsWith("x-");
    }
    
    public abstract boolean contains(Charset cs);
    public abstract CharsetDecoder newDecoder();
    public abstract CharsetEncoder newEncoder();
    
    public final ByteBuffer encode(CharBuffer cb) {
        try {
            return newEncoder()
                .onMalformedInput(CodingErrorAction.REPLACE)
                .onUnmappableCharacter(CodingErrorAction.REPLACE)
                .encode(cb);
        } catch (CharacterCodingException x) {
            throw new Error(x);  // Should not happen
        }
    }
    
    public final ByteBuffer encode(String str) {
        return encode(CharBuffer.wrap(str));
    }
    
    public final CharBuffer decode(ByteBuffer bb) {
        try {
            return newDecoder()
                .onMalformedInput(CodingErrorAction.REPLACE)
                .onUnmappableCharacter(CodingErrorAction.REPLACE)
                .decode(bb);
        } catch (CharacterCodingException x) {
            throw new Error(x);  // Should not happen
        }
    }
    
    public static Charset forName(String charsetName) {
        Charset cs = lookup(charsetName);
        if (cs != null)
            return cs;
        throw new UnsupportedCharsetException(charsetName);
    }
    
    public static SortedMap<String, Charset> availableCharsets() {
        return sun.nio.cs.StandardCharsets.aliases();
    }
    
    public static boolean isSupported(String charsetName) {
        return lookup(charsetName) != null;
    }
    
    public static Charset defaultCharset() {
        if (defaultCharset == null) {
            synchronized (Charset.class) {
                String csn = StaticProperty.jdkNativeEncoding();
                Charset cs = lookup(csn);
                if (cs == null)
                    cs = sun.nio.cs.UTF_8.INSTANCE;
                defaultCharset = cs;
            }
        }
        return defaultCharset;
    }
    
    @Override
    public final int compareTo(Charset that) {
        return name.compareToIgnoreCase(that.name);
    }
    
    @Override
    public final boolean equals(Object ob) {
        if (!(ob instanceof Charset))
            return false;
        if (this == ob)
            return true;
        return name.equalsIgnoreCase(((Charset)ob).name());
    }
    
    @Override
    public final int hashCode() {
        return name.toUpperCase(Locale.ROOT).hashCode();
    }
    
    @Override
    public final String toString() {
        return name;
    }
}