ASCII Table — Java source
A searchable, filterable reference for all 128 ASCII code points. See the decimal, hex, octal, and binary form of every character, narrow to printable characters only, clamp the code-point range, and click any row to copy. Runs 100% client-side.
This is the Java implementation — the same logic the interactive tool runs, in a shareable, citable form.
// ASCII Table — pure logic (Java port): the 128-entry ASCII reference table with
// search and range filters.
//
// Language: Java 17 — standard library only (java.lang / java.util).
// Source: CosmoDev polyglot showcase port; canonical = src/lib/ascii-table.ts
// + this tool's python.py / rust.rs.
// License: display source — part of CosmoDev's polyglot tool pages.
//
// Each of the 128 ASCII code points is described by its decimal / hex / octal /
// binary forms, a display glyph, a human name, whether it is printable, whether
// it is a control character, and (for control chars that have one) a C-style
// escape sequence.
//
// The types are package-private: the polyglot layout fixes this file's name
// (java.java), so it cannot match the type name as javac requires for public
// top-level types.
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
/**
* A single ASCII code point and its derived representations.
*
* @param dec decimal code point, 0–127
* @param hex uppercase hex, e.g. "0x41"
* @param oct zero-padded 3-digit octal, e.g. "101"
* @param binary zero-padded 8-bit binary, e.g. "01000001"
* @param glyph display glyph: the literal char for printables, a
* control-picture glyph otherwise (named {@code char} in the
* canonical sources; that is a keyword here)
* @param name human-readable name, e.g. "Line Feed (LF)", "Uppercase A"
* @param printable true for 32–126 (visible or space)
* @param control true for 0–31 and 127
* @param escape C-style escape for control chars that have one (e.g. "\n");
* null otherwise
*/
record Entry(int dec, String hex, String oct, String binary, String glyph, String name,
boolean printable, boolean control, String escape) {
}
/** The {@code ascii-table} tool's pure logic. */
final class AsciiTable {
private AsciiTable() {
}
/**
* Official ASCII control-character names for 0–31 and 127.
*
* <p>Expressed as a switch expression over every control code point; the
* default arm is a defensive guard that documents the precondition (the
* Rust port uses {@code unreachable!()} for the same case).
*/
private static String controlName(int code) {
return switch (code) {
case 0 -> "Null (NUL)";
case 1 -> "Start of Heading (SOH)";
case 2 -> "Start of Text (STX)";
case 3 -> "End of Text (ETX)";
case 4 -> "End of Transmission (EOT)";
case 5 -> "Enquiry (ENQ)";
case 6 -> "Acknowledge (ACK)";
case 7 -> "Bell (BEL)";
case 8 -> "Backspace (BS)";
case 9 -> "Horizontal Tab (HT)";
case 10 -> "Line Feed (LF)";
case 11 -> "Vertical Tab (VT)";
case 12 -> "Form Feed (FF)";
case 13 -> "Carriage Return (CR)";
case 14 -> "Shift Out (SO)";
case 15 -> "Shift In (SI)";
case 16 -> "Data Link Escape (DLE)";
case 17 -> "Device Control 1 (DC1)";
case 18 -> "Device Control 2 (DC2)";
case 19 -> "Device Control 3 (DC3)";
case 20 -> "Device Control 4 (DC4)";
case 21 -> "Negative Acknowledge (NAK)";
case 22 -> "Synchronous Idle (SYN)";
case 23 -> "End of Transmission Block (ETB)";
case 24 -> "Cancel (CAN)";
case 25 -> "End of Medium (EM)";
case 26 -> "Substitute (SUB)";
case 27 -> "Escape (ESC)";
case 28 -> "File Separator (FS)";
case 29 -> "Group Separator (GS)";
case 30 -> "Record Separator (RS)";
case 31 -> "Unit Separator (US)";
case 127 -> "Delete (DEL)";
// Only called with control codes; defensive guard for misuse.
default -> "";
};
}
/**
* C-style escape for the control chars that own a standard/common one.
* Returns the literal 2-character source token (backslash + letter), or null.
*/
private static String controlEscape(int code) {
return switch (code) {
case 0 -> "\\0";
case 7 -> "\\a";
case 8 -> "\\b";
case 9 -> "\\t";
case 10 -> "\\n";
case 11 -> "\\v";
case 12 -> "\\f";
case 13 -> "\\r";
case 27 -> "\\e";
default -> null;
};
}
/**
* Name for a printable punctuation / symbol glyph, or null.
* Letters and digits are derived in {@link #letterName(int)}.
*/
private static String symbolName(int code) {
return switch (code) {
case 32 -> "Space";
case 33 -> "Exclamation mark";
case 34 -> "Quotation mark";
case 35 -> "Number sign";
case 36 -> "Dollar sign";
case 37 -> "Percent sign";
case 38 -> "Ampersand";
case 39 -> "Apostrophe";
case 40 -> "Left parenthesis";
case 41 -> "Right parenthesis";
case 42 -> "Asterisk";
case 43 -> "Plus sign";
case 44 -> "Comma";
case 45 -> "Hyphen / Minus";
case 46 -> "Full stop";
case 47 -> "Slash";
case 58 -> "Colon";
case 59 -> "Semicolon";
case 60 -> "Less-than sign";
case 61 -> "Equals sign";
case 62 -> "Greater-than sign";
case 63 -> "Question mark";
case 64 -> "At sign";
case 91 -> "Left bracket";
case 92 -> "Backslash";
case 93 -> "Right bracket";
case 94 -> "Circumflex / Caret";
case 95 -> "Underscore";
case 96 -> "Grave accent";
case 123 -> "Left brace";
case 124 -> "Vertical bar";
case 125 -> "Right brace";
case 126 -> "Tilde";
default -> null;
};
}
/** Derive a name for a printable letter or digit. */
private static String letterName(int code) {
if (code >= 48 && code <= 57) // '0'..'9'
return "Digit " + (code - 48);
if (code >= 65 && code <= 90) // 'A'..'Z'
return "Uppercase " + (char) code;
if (code >= 97 && code <= 122) // 'a'..'z'
return "Lowercase " + (char) code;
return String.valueOf((char) code);
}
/** Zero-pad a radix string to {@code width} digits (Java has no "%b"/width fill for binary). */
private static String pad(String digits, int width) {
return "0".repeat(width - digits.length()) + digits;
}
/** Build a single entry from its code point (0–127). */
private static Entry makeEntry(int code) {
boolean control = code <= 31 || code == 127;
// Control-picture glyph: U+2400 for 0–31, U+2421 ("symbol for delete") for DEL.
String glyph = control
? new String(Character.toChars(code == 127 ? 0x2421 : 0x2400 + code))
: String.valueOf((char) code);
String symbol = symbolName(code);
String name = control ? controlName(code)
: symbol != null ? symbol : letterName(code);
return new Entry(
code,
String.format("0x%02X", code),
String.format("%03o", code),
pad(Integer.toBinaryString(code), 8),
glyph,
name,
!control,
control,
control ? controlEscape(code) : null);
}
// The 128-entry table is built once in the class initializer. The JLS
// (§12.4.2) guarantees class initialization runs exactly once,
// thread-safely — the JVM equivalent of Rust's OnceLock.
private static final List<Entry> ENTRIES = buildEntries();
private static List<Entry> buildEntries() {
List<Entry> table = new ArrayList<>(128);
for (int i = 0; i < 128; i++)
table.add(makeEntry(i));
return List.copyOf(table);
}
/** The full 128-entry ASCII table, indexed by code point (immutable). */
public static List<Entry> entries() {
return ENTRIES;
}
/**
* Look up a single entry by code point.
*
* <p>Returns {@link Optional#empty()} for out-of-range input — the idiomatic
* Java equivalent of the TypeScript variant's null and Rust's Option,
* forcing callers to handle absence.
*/
public static Optional<Entry> getEntry(int code) {
if (code < 0 || code > 127)
return Optional.empty();
return Optional.of(ENTRIES.get(code));
}
/** {@link #filterTable} with all defaults. */
public static List<Entry> filterTable() {
return filterTable("", false, 0, 127);
}
/**
* Filter the table.
*
* <p>{@code query} is a case-insensitive substring matched against dec /
* hex / oct / binary / name / char / escape. {@code printableOnly} hides
* controls. {@code min} / {@code max} clamp the decimal range (defaults
* 0–127).
*/
public static List<Entry> filterTable(String query, boolean printableOnly, int min, int max) {
String q = (query == null ? "" : query).strip().toLowerCase(Locale.ROOT);
List<Entry> result = new ArrayList<>();
for (Entry e : ENTRIES) {
if (printableOnly && !e.printable())
continue;
if (e.dec() < min || e.dec() > max)
continue;
if (!q.isEmpty()) {
boolean hit = Integer.toString(e.dec()).contains(q)
|| e.hex().toLowerCase(Locale.ROOT).contains(q)
|| e.oct().contains(q)
|| e.binary().contains(q)
|| e.name().toLowerCase(Locale.ROOT).contains(q)
|| e.glyph().toLowerCase(Locale.ROOT).contains(q)
|| (e.escape() != null && e.escape().contains(q));
if (!hit)
continue;
}
result.add(e);
}
return result;
}
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →