I'm using the following code to Parse CSV file in Apex:

public static List<List<String>> parseCSV(String contents,Boolean skipHeaders) {
    List<List<String>> allFields = new List<List<String>>();

    // replace instances where a double quote begins a field containing a comma
    // in this case you get a double quote followed by a doubled double quote
    // do this for beginning and end of a field
    contents = contents.replaceAll(',"""',',"DBLQT').replaceall('""",','DBLQT",');
    // now replace all remaining double quotes - we do this so that we can reconstruct
    // fields with commas inside assuming they begin and end with a double quote
    contents = contents.replaceAll('""','DBLQT');
    // we are not attempting to handle fields with a newline inside of them
    // so, split on newline to get the spreadsheet rows
    List<String> lines = new List<String>();
    try {
        lines = contents.split('\n');
    } catch (System.ListException e) {
        System.debug('Limits exceeded?' + e.getMessage());
    Integer num = 0;
    for(String line : lines) {
        // check for blank CSV lines (only commas)
        if (line.replaceAll(',','').trim().length() == 0) break;

        List<String> fields = line.split(',');  
        List<String> cleanFields = new List<String>();
        String compositeField;
        Boolean makeCompositeField = false;
        for(String field : fields) {
            if (field.startsWith('"') && field.endsWith('"')) {
            } else if (field.startsWith('"')) {
                makeCompositeField = true;
                compositeField = field;
            } else if (field.endsWith('"')) {
                compositeField += ',' + field;
                makeCompositeField = false;
            } else if (makeCompositeField) {
                compositeField +=  ',' + field;
            } else {

    if (skipHeaders) allFields.remove(0);
    return allFields;       

The code was taken from the following article: https://developer.salesforce.com/page/Code_Samples#Parse_a_CSV_with_APEX

After I invoke the method the return result is giving me incorrect new line on incorrect place.

Here is the result I received in the debug log:

enter image description here

I was looking at the code but not able to figured out why there is a new line before the closing bracket?

  • P.S. You can't catch a LimitException, which is what split('\n') would return if you break limits.
    – sfdcfox
    Commented Mar 12, 2018 at 19:01

2 Answers 2


Basically, you should call a replaceAll beforehand:

contents = contents.replaceAll('(\r\n|\r)','\n');

This code normalizes CRLF and CR to use just LF. Note that CSV may be in any of those three formats (CRLF, CR, or LF), depending on the source system (Windows, Mac, and Linux, respectively).

Also note that the last line might be empty, depending on the system, so check for this and remove it, if necessary:

if(String.isBlank(lines[lines.size()-1])) {

Also, you need to take care of replacement/normalizing CRLF, CR at the end of the string. Some fields might have this characters (a rare situation). Correct code should be

contents = contents.replaceAll('(\r\n|\r)$','\n');

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .