public static List<String> csvSplit(List<String> list, String s, int off, int len) {
        if (list == null)
            list = new ArrayList<>();
        CsvSplitState state = CsvSplitState.PRE_DATA;
        StringBuilder out = new StringBuilder();
        int last = -1;
        while (len > 0) {
            char ch = s.charAt(off++);
            len--;

            switch (state) {
                case PRE_DATA:
                    if (Character.isWhitespace(ch))
                        continue;

                    if ('"' == ch) {
                        state = CsvSplitState.QUOTE;
                        continue;
                    }

                    if (',' == ch) {
                        list.add("");
                        continue;
                    }

                    state = CsvSplitState.DATA;
                    out.append(ch);
                    continue;

                case DATA:
                    if (Character.isWhitespace(ch)) {
                        last = out.length();
                        out.append(ch);
                        state = CsvSplitState.WHITE;
                        continue;
                    }

                    if (',' == ch) {
                        list.add(out.toString());
                        out.setLength(0);
                        state = CsvSplitState.PRE_DATA;
                        continue;
                    }

                    out.append(ch);
                    continue;

                case WHITE:
                    if (Character.isWhitespace(ch)) {
                        out.append(ch);
                        continue;
                    }

                    if (',' == ch) {
                        out.setLength(last);
                        list.add(out.toString());
                        out.setLength(0);
                        state = CsvSplitState.PRE_DATA;
                        continue;
                    }

                    state = CsvSplitState.DATA;
                    out.append(ch);
                    last = -1;
                    continue;

                case QUOTE:
                    if ('\\' == ch) {
                        state = CsvSplitState.SLOSH;
                        continue;
                    }
                    if ('"' == ch) {
                        list.add(out.toString());
                        out.setLength(0);
                        state = CsvSplitState.POST_DATA;
                        continue;
                    }
                    out.append(ch);
                    continue;

                case SLOSH:
                    out.append(ch);
                    state = CsvSplitState.QUOTE;
                    continue;

                case POST_DATA:
                    if (',' == ch) {
                        state = CsvSplitState.PRE_DATA;
                    }
            }
        }

        switch (state) {
            case PRE_DATA:
            case POST_DATA:
                break;

            case DATA:
            case QUOTE:
            case SLOSH:
                list.add(out.toString());
                break;

            case WHITE:
                out.setLength(last);
                list.add(out.toString());
                break;
        }

        return list;
    }
public static List < String > csvSplit ( List < String > list , String s , int off , int len ) { if ( list == null ) list = new ArrayList < > ( ) ; CsvSplitState state = CsvSplitState . PRE_DATA ; StringBuilder out = new StringBuilder ( ) ; int last = - 1 ; while ( len > 0 ) { char ch = s . charAt ( off ++ ) ; len -- ; switch ( state ) { case PRE_DATA : if ( Character . isWhitespace ( ch ) ) continue ; if ( '"' == ch ) { state = CsvSplitState . QUOTE ; continue ; } if ( ',' == ch ) { list . add ( "" ) ; continue ; } state = CsvSplitState . DATA ; out . append ( ch ) ; continue ; case DATA : if ( Character . isWhitespace ( ch ) ) { last = out . length ( ) ; out . append ( ch ) ; state = CsvSplitState . WHITE ; continue ; } if ( ',' == ch ) { list . add ( out . toString ( ) ) ; out . setLength ( 0 ) ; state = CsvSplitState . PRE_DATA ; continue ; } out . append ( ch ) ; continue ; case WHITE : if ( Character . isWhitespace ( ch ) ) { out . append ( ch ) ; continue ; } if ( ',' == ch ) { out . setLength ( last ) ; list . add ( out . toString ( ) ) ; out . setLength ( 0 ) ; state = CsvSplitState . PRE_DATA ; continue ; } state = CsvSplitState . DATA ; out . append ( ch ) ; last = - 1 ; continue ; case QUOTE : if ( '\\' == ch ) { state = CsvSplitState . SLOSH ; continue ; } if ( '"' == ch ) { list . add ( out . toString ( ) ) ; out . setLength ( 0 ) ; state = CsvSplitState . POST_DATA ; continue ; } out . append ( ch ) ; continue ; case SLOSH : out . append ( ch ) ; state = CsvSplitState . QUOTE ; continue ; case POST_DATA : if ( ',' == ch ) { state = CsvSplitState . PRE_DATA ; } } } switch ( state ) { case PRE_DATA : case POST_DATA : break ; case DATA : case QUOTE : case SLOSH : list . add ( out . toString ( ) ) ; break ; case WHITE : out . setLength ( last ) ; list . add ( out . toString ( ) ) ; break ; } return list ; }
Split a quoted comma separated string to a list
<p>
Handle <a href="https://www.ietf.org/rfc/rfc4180.txt">rfc4180</a>-like
CSV strings, with the exceptions:
<ul>
<li>quoted values may contain double quotes escaped with back-slash
<li>Non-quoted values are trimmed of leading trailing white space
<li>trailing commas are ignored
<li>double commas result in a empty string value
</ul>

@param list The Collection to split to (or null to get a new list)
@param s    The string to parse
@param off  The offset into the string to start parsing
@param len  The len in characters to parse
@return list containing the parsed list values