12

How can I convert a text file or a String from UTF-8 format to ASCII?

For example, the following string "ZÜRICH-ZOLLI" once outputted into a text file. If the file has the format UTF-8 is has 13 characters but when the format is ASCII the number of characters is 12.

The endpoint where the file is being sent only accepts the ASCII-encoded version, and fails on the UTF-8 encoded string salesforce normally produces.

3 Answers 3

12

UTF-8 is a superset of ASCII. The character codes 0-127 (i.e. the ASCII characters) are directly mapped to the binary values 0-127 so if your UTF-8 string only consists of ASCII characters it is already in ASCII format.

Beyond that all you can really do is strip out the non-ascii characters from your string or replace them with some ASCII character. This regex should do it for you.

if(!str.isAsciiPrintable) str = str.replaceall('[^\\x00-\\x7F]', '');
1
  • This answer is mostly correct; the "extended" ASCII 0x80-0xFF are mapped elsewhere in UTF-8 (obviously, because the MSB is commandeered by UTF-8 for extending a character code). Still, an excellent answer.
    – sfdcfox
    Commented Apr 13, 2022 at 18:36
8
data = EncodingUtil.urlEncode(data, 'ASCII');
data = EncodingUtil.urlDecode(data, 'ASCII');

(What if there is a byte order marker?)

4
  • 2
    this worked for me! and I was able to strip the remnant byte order mark as well
    – Wesley
    Commented Jan 18, 2013 at 12:48
  • That's interesting. I guess this would depend on whether you want to strip out the characters or replace with a '?'. Though of course you could easily modify replaceall to use a '?'. Commented Jan 18, 2013 at 19:11
  • 1
    the ?s are a bummer :( off-platform, iconv //TRANSLIT could at least represent Ü as U Commented Jan 18, 2013 at 20:43
  • Can this be done in a formula, for a formula field? Or does it have to be Apex code? Commented Jun 8, 2023 at 15:30
1
  //parsing csv blob file to proper format
  string csvAsString = ApexController.blobToString(csvblobfile.body,'ISO 8859-2');
   //parse CSV
  List<List<String>> parsedCSVRecords = ApexController.parseCSV(csvAsString,false);


  //Add below static methods in your controller

   public Class ApexController{

   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());
    }
    system.debug('Line num i s'+lines.size());
    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('"')) {
                cleanFields.add(field.replaceAll('DBLQT','"'));
            } else if (field.startsWith('"')) {
                makeCompositeField = true;
                compositeField = field;
            } else if (field.endsWith('"')) {
                compositeField += ',' + field;
                cleanFields.add(compositeField.replaceAll('DBLQT','"'));
                makeCompositeField = false;
            } else if (makeCompositeField) {
                compositeField +=  ',' + field;
            } else {
                cleanFields.add(field.replaceAll('DBLQT','"'));
            }
        }

        allFields.add(cleanFields);
    }
    if (skipHeaders) allFields.remove(0);
    return allFields;       
} 


  public static String blobToString(Blob input, String inCharset){
     String hex = EncodingUtil.convertToHex(input);
     System.assertEquals(0, hex.length() & 1);
    final Integer bytesCount = hex.length() >> 1;
    String[] bytes = new String[bytesCount];
    for(Integer i = 0; i < bytesCount; ++i)
    bytes[i] =  hex.mid(i << 1, 2);
    return EncodingUtil.urlDecode('%' + String.join(bytes, '%'), inCharset);
 }
4
  • 2
    Can you please explain what your code is suppose to do ?
    – SF_user
    Commented Jun 8, 2015 at 7:29
  • This code will parse non utf csv files . blobToString function can convert any input blob to specific string format like UTF-8,ISO 8859-2 etc.. Commented Jun 17, 2015 at 5:01
  • @DebadyutiSil String blobToString(Blob input, String inCharset) is a great solution to convert a non-UTF-8 Blob to UTF-8. Thanks! Commented Jan 26, 2018 at 22:09
  • @DebadyutiSil, in static String blobToString(...), why do you assert hex's length is even? Won't EncodingUtil's convertToHex always return a String of even length? (Plus, you can't catch asserts, so why have it?) EncodingUtil class: developer.salesforce.com/docs/atlas.en-us.apexcode.meta/… Commented Jan 30, 2018 at 14:54

You must log in to answer this question.

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