private static Pair<Character,Integer> normalizeCodepoint(String origString_,Charset encoding_,int offset_){
  char normalizedChar='?';
  boolean isOk=false;
  final int codepoint=origString_.codePointAt(offset_);
  if (encoding_.equals(Charset.forName("US-ASCII"))) {
    if (codepoint < 128)     isOk=true;
  }
 else   if (encoding_.equals(Charset.forName("ISO-8859-1"))) {
    if (codepoint < 256)     isOk=true;
  }
 else   if (encoding_.equals(Charset.forName("UTF-8"))) {
    if (codepoint < 1114111)     isOk=true;
  }
  if (isOk) {
    normalizedChar=(char)codepoint;
  }
 else {
    isOk=true;
    final int type=Character.getType(codepoint);
    if (type == Character.CURRENCY_SYMBOL)     normalizedChar='$';
 else     if (type == Character.DASH_PUNCTUATION)     normalizedChar='-';
 else     if (type == Character.FINAL_QUOTE_PUNCTUATION) {
      normalizedChar='"';
    }
 else     if (type == Character.INITIAL_QUOTE_PUNCTUATION) {
      normalizedChar='"';
    }
 else     if (type == Character.END_PUNCTUATION)     normalizedChar='.';
 else     if (type == Character.DASH_PUNCTUATION)     normalizedChar='-';
 else     if (type == Character.OTHER_LETTER)     normalizedChar='a';
 else     if (type == Character.OTHER_NUMBER)     normalizedChar='0';
 else     if (type == Character.OTHER_PUNCTUATION)     normalizedChar='-';
 else     if (type == Character.OTHER_SYMBOL)     normalizedChar=' ';
 else     isOk=false;
  }
  Character newChar=null;
  if (isOk)   newChar=normalizedChar;
  return new Pair<>(newChar,codepoint);
}

private static Pair < Character , Integer > normalizeCodepoint ( String origString_ , Charset encoding_ , int offset_ ) { char normalizedChar = '?' ; boolean isOk = false ; final int codepoint = origString_ . codePointAt ( offset_ ) ; if ( encoding_ . equals ( Charset . forName ( "US-ASCII" ) ) ) { if ( codepoint < 128 ) isOk = true ; } else if ( encoding_ . equals ( Charset . forName ( "ISO-8859-1" ) ) ) { if ( codepoint < 256 ) isOk = true ; } else if ( encoding_ . equals ( Charset . forName ( "UTF-8" ) ) ) { if ( codepoint < 1114111 ) isOk = true ; } if ( isOk ) { normalizedChar = ( char ) codepoint ; } else { isOk = true ; final int type = Character . getType ( codepoint ) ; if ( type == Character . CURRENCY_SYMBOL ) normalizedChar = '$' ; else if ( type == Character . DASH_PUNCTUATION ) normalizedChar = '-' ; else if ( type == Character . FINAL_QUOTE_PUNCTUATION ) { normalizedChar = '"' ; } else if ( type == Character . INITIAL_QUOTE_PUNCTUATION ) { normalizedChar = '"' ; } else if ( type == Character . END_PUNCTUATION ) normalizedChar = '.' ; else if ( type == Character . DASH_PUNCTUATION ) normalizedChar = '-' ; else if ( type == Character . OTHER_LETTER ) normalizedChar = 'a' ; else if ( type == Character . OTHER_NUMBER ) normalizedChar = '0' ; else if ( type == Character . OTHER_PUNCTUATION ) normalizedChar = '-' ; else if ( type == Character . OTHER_SYMBOL ) normalizedChar = ' ' ; else isOk = false ; } Character newChar = null ; if ( isOk ) newChar = normalizedChar ; return new Pair < > ( newChar , codepoint ) ; }
substitute based on types : for a character encoding not in range , replace punctuation with generic punctuation whitespace with whitespace letter with letter number with number currency symbol with currency
