RTEditor/src/main/java/com/onegravity/rteditor/utils/io/FilenameUtils.java
private static String doNormalize(String filename, char separator, boolean keepSeparator) {
        if (filename == null) {
            return null;
        }
        int size = filename.length();
        if (size == 0) {
            return filename;
        }
        int prefix = getPrefixLength(filename);
        if (prefix < 0) {
            return null;
        }
        
        char[] array = new char[size + 2];  // +1 for possible extra slash, +2 for arraycopy
        filename.getChars(0, filename.length(), array, 0);
        
        // fix separators throughout
        char otherSeparator = separator == SYSTEM_SEPARATOR ? OTHER_SEPARATOR : SYSTEM_SEPARATOR;
        for (int i = 0; i < array.length; i++) {
            if (array[i] == otherSeparator) {
                array[i] = separator;
            }
        }
        
        // add extra separator on the end to simplify code below
        boolean lastIsDirectory = true;
        if (array[size - 1] != separator) {
            array[size++] = separator;
            lastIsDirectory = false;
        }
        
        // adjoining slashes
        for (int i = prefix + 1; i < size; i++) {
            if (array[i] == separator && array[i - 1] == separator) {
                System.arraycopy(array, i, array, i - 1, size - i);
                size--;
                i--;
            }
        }
        
        // dot slash
        for (int i = prefix + 1; i < size; i++) {
            if (array[i] == separator && array[i - 1] == '.' &&
                    (i == prefix + 1 || array[i - 2] == separator)) {
                if (i == size - 1) {
                    lastIsDirectory = true;
                }
                System.arraycopy(array, i + 1, array, i - 1, size - i);
                size -=2;
                i--;
            }
        }
        
        // double dot slash
        outer:
        for (int i = prefix + 2; i < size; i++) {
            if (array[i] == separator && array[i - 1] == '.' && array[i - 2] == '.' &&
                    (i == prefix + 2 || array[i - 3] == separator)) {
                if (i == prefix + 2) {
                    return null;
                }
                if (i == size - 1) {
                    lastIsDirectory = true;
                }
                int j;
                for (j = i - 4 ; j >= prefix; j--) {
                    if (array[j] == separator) {
                        // remove b/../ from a/b/../c
                        System.arraycopy(array, i + 1, array, j + 1, size - i);
                        size -= i - j;
                        i = j + 1;
                        continue outer;
                    }
                }
                // remove a/../ from a/../c
                System.arraycopy(array, i + 1, array, prefix, size - i);
                size -= i + 1 - prefix;
                i = prefix + 1;
            }
        }
        
        if (size <= 0) {  // should never be less than 0
            return "";
        }
        if (size <= prefix) {  // should never be less than prefix
            return new String(array, 0, size);
        }
        if (lastIsDirectory && keepSeparator) {
            return new String(array, 0, size);  // keep trailing separator
        }
        return new String(array, 0, size - 1);  // lose trailing separator
    }
private static String doNormalize(String filename, char separator, boolean keepSeparator) {
        if (filename == null) {
            return null;
        }
        int size = filename.length();
        if (size == 0) {
            return filename;
        }
        int prefix = getPrefixLength(filename);
        if (prefix < 0) {
            return null;
        }
        
        char[] array = new char[size + 2];  // +1 for possible extra slash, +2 for arraycopy
        filename.getChars(0, filename.length(), array, 0);
        
        // fix separators throughout
        char otherSeparator = separator == SYSTEM_SEPARATOR ? OTHER_SEPARATOR : SYSTEM_SEPARATOR;
        for (int i = 0; i < array.length; i++) {
            if (array[i] == otherSeparator) {
                array[i] = separator;
            }
        }
        
        // add extra separator on the end to simplify code below
        boolean lastIsDirectory = true;
        if (array[size - 1] != separator) {
            array[size++] = separator;
            lastIsDirectory = false;
        }
        
        // adjoining slashes
        for (int i = prefix + 1; i < size; i++) {
            if (array[i] == separator && array[i - 1] == separator) {
                System.arraycopy(array, i, array, i - 1, size - i);
                size--;
                i--;
            }
        }
        
        // dot slash
        for (int i = prefix + 1; i < size; i++) {
            if (array[i] == separator && array[i - 1] == '.' &&
                    (i == prefix + 1 || array[i - 2] == separator)) {
                if (i == size - 1) {
                    lastIsDirectory = true;
                }
                System.arraycopy(array, i + 1, array, i - 1, size - i);
                size -=2;
                i--;
            }
        }
        
        // double dot slash
        outer:
        for (int i = prefix + 2; i < size; i++) {
            if (array[i] == separator && array[i - 1] == '.' && array[i - 2] == '.' &&
                    (i == prefix + 2 || array[i - 3] == separator)) {
                if (i == prefix + 2) {
                    return null;
                }
                if (i == size - 1) {
                    lastIsDirectory = true;
                }
                int j;
                for (j = i - 4 ; j >= prefix; j--) {
                    if (array[j] == separator) {
                        // remove b/../ from a/b/../c
                        System.arraycopy(array, i + 1, array, j + 1, size - i);
                        size -= i - j;
                        i = j + 1;
                        continue outer;
                    }
                }
                // remove a/../ from a/../c
                System.arraycopy(array, i + 1, array, prefix, size - i);
                size -= i + 1 - prefix;
                i = prefix + 1;
            }
        }
        
        if (size <= 0) {  // should never be less than 0
            return "";
        }
        if (size <= prefix) {  // should never be less than prefix
            return new String(array, 0, size);
        }
        if (lastIsDirectory && keepSeparator) {
            return new String(array, 0, size);  // keep trailing separator
        }
        return new String(array, 0, size - 1);  // lose trailing separator
    }
private static String doNormalize ( String filename , char separator , boolean keepSeparator ) { if ( filename == null ) { return null ; } int size = filename . length ( ) ; if ( size == 0 ) { return filename ; } int prefix = getPrefixLength ( filename ) ; if ( prefix < 0 ) { return null ; } char [ ] array = new char [ size + 2 ] ; // +1 for possible extra slash, +2 for arraycopy filename . getChars ( 0 , filename . length ( ) , array , 0 ) ; // fix separators throughout char otherSeparator = separator == SYSTEM_SEPARATOR ? OTHER_SEPARATOR : SYSTEM_SEPARATOR ; for ( int i = 0 ; i < array . length ; i ++ ) { if ( array [ i ] == otherSeparator ) { array [ i ] = separator ; } } // add extra separator on the end to simplify code below boolean lastIsDirectory = true ; if ( array [ size - 1 ] != separator ) { array [ size ++ ] = separator ; lastIsDirectory = false ; } // adjoining slashes for ( int i = prefix + 1 ; i < size ; i ++ ) { if ( array [ i ] == separator && array [ i - 1 ] == separator ) { System . arraycopy ( array , i , array , i - 1 , size - i ) ; size -- ; i -- ; } } // dot slash for ( int i = prefix + 1 ; i < size ; i ++ ) { if ( array [ i ] == separator && array [ i - 1 ] == ' ' && ( i == prefix + 1 || array [ i - 2 ] == separator ) ) { if ( i == size - 1 ) { lastIsDirectory = true ; } System . arraycopy ( array , i + 1 , array , i - 1 , size - i ) ; size -= 2 ; i -- ; } } // double dot slash outer : for ( int i = prefix + 2 ; i < size ; i ++ ) { if ( array [ i ] == separator && array [ i - 1 ] == ' ' && array [ i - 2 ] == ' ' && ( i == prefix + 2 || array [ i - 3 ] == separator ) ) { if ( i == prefix + 2 ) { return null ; } if ( i == size - 1 ) { lastIsDirectory = true ; } int j ; for ( j = i - 4 ; j >= prefix ; j -- ) { if ( array [ j ] == separator ) { // remove b/../ from a/b/../c System . arraycopy ( array , i + 1 , array , j + 1 , size - i ) ; size -= i - j ; i = j + 1 ; continue outer ; } } // remove a/../ from a/../c System . arraycopy ( array , i + 1 , array , prefix , size - i ) ; size -= i + 1 - prefix ; i = prefix + 1 ; } } if ( size <= 0 ) { // should never be less than 0 return "" ; } if ( size <= prefix ) { // should never be less than prefix return new String ( array , 0 , size ) ; } if ( lastIsDirectory && keepSeparator ) { return new String ( array , 0 , size ) ; // keep trailing separator } return new String ( array , 0 , size - 1 ) ; // lose trailing separator }
Internal method to perform the normalization.

@param filename  the filename
@param separator The separator character to use
@param keepSeparator  true to keep the final separator
@return the normalized filename
Internal method to perform the normalization .