Dev Center
Table of contents

Thanks for downloading Dynamsoft Barcode Reader Package!

Your download will start shortly. If your download does not begin, click here to retry.

How to Handle Non-printable Characters Like “\u{1D}” or “{GS}” from the Barcode Text?

This page helps to you modify the barcode results when non-printable characters exists in the barcode text you decoded.

You always get 2 values that stands for the barcode decoding result from the CBarcodeResultItem object:

  • barcodeBytes
  • barcodeText

Since barcodeText is a string value that generated from the barcodeBytes, is might be decoded into different characters based on different character encoding formats. When there exists a non-printable ASCII value (0 ~ 31 or 127) in the barcodeBytes array, the value is decoded into a messy code. Currently, the library doesn’t provide methods to remove the non-printable characters nor convert them into printable characters, you have to add your own code to recognize the non-printable characters and replace or remove them. The following code snippet is an example for how to create a method for processing the barcodeBytes into a string you want.

Code Snippet

  • C++
  • Android
  • Objective-C
  • Swift
#include <string>
#include <map>
typedef enum ProcessNonPrintingCharsMode
{
    PNPCM_KEEP,
    PNPCM_REMOVE,
    PNPCM_CONVERT
}ProcessNonPrintingCharsMode;
class ProcessBarcodeBytesUtil
{
private:
    std::map<int, std::string> charValueToStringDict;
public:
    ProcessBarcodeBytesUtil()
    {
        int NonPrintingAsciiCharsValue[33] = {
            0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x7f
        };
        const char* NonPrintingAsciiCharsString[33] = {
            "{NUL}","{SOH}","{STX}","{ETX}","{EOT}","{ENQ}","{ACK}","{BEL}","{BS}","{HT}","{LF}","{VT}","{FF}","{CR}","{SO}","{SI}","{DLE}","{DC1}","{DC2}","{DC3}","{DC4}","{NAK}","{SYN}","{ETB}","{CAN}","{EM}","{SUB}","{ESC}","{FS}","{GS}","{RS}","{US}","{DEL}"
        };
        for (int i = 0; i < 33; ++i)
            charValueToStringDict.insert(std::make_pair(NonPrintingAsciiCharsValue[i], NonPrintingAsciiCharsString[i]));
        }
        /**
        * Process the non-printing chars of barcode bytes to obtain desired text.
        *
        * @param [in] bytes The barcode content in a byte array.
        * @param [in] bytesLength The length of the byte array.
        * @param [in] mode The mode indicates how to processing non-printing chars.
        * @param [in] keepLineBreak The flag indicates whether to preserve the original line breaks in the resulting text. It is only valid when mode is PNPCM_REMOVE or PNPCM_CONVERT.
        *
        * @return Returns The text result after processing barcode bytes.
        *
        */
        std::string processBarcodeBytes(unsigned char* bytes, int bytesLength, ProcessNonPrintingCharsMode mode, bool keepLineBreak = true) {
        std::string result;
        for (int i = 0; i < bytesLength; ++i)
        {
            int byteValue = (int)bytes[i];
            if (charValueToStringDict.find(byteValue) == charValueToStringDict.end()
                || mode == PNPCM_KEEP
                || keepLineBreak && (byteValue == 10 || byteValue == 13)) {
                    result.append(1, bytes[i]);
                }
            else if (mode == PNPCM_CONVERT) {
                result.append(charValueToStringDict[byteValue]);
            }
        }
        return result;
    }
};
int main()
{
    // obtain bytes from CBarcodeResultItem.
    unsigned char* barcodeBytes = barcodeResult->GetBytes();
    int bytesLength = barcodeResult->GetBytesLength();
    ProcessBarcodeBytesUtil util;
    std::string originStr = util.processBarcodeBytes(barcodeBytes, bytesLength, PNPCM_KEEP);
    std::cout << "1.original text:" << std::endl << originStr << std::endl << std::endl;
    std::string strAfterRemoveExceptLineBreack = util.processBarcodeBytes(barcodeBytes, bytesLength, PNPCM_REMOVE);
    std::cout << "2.text after removing non-printing chars except line break:" << std::endl << strAfterRemoveExceptLineBreack << std::endl << std::endl;
    std::string strAfterRemove= util.processBarcodeBytes(barcodeBytes, bytesLength, PNPCM_REMOVE, false);
    std::cout << "3.text after removing non-printing chars:" << std::endl << strAfterRemove << std::endl << std::endl;
    std::string strAfterConvertExceptLineBreack = util.processBarcodeBytes(barcodeBytes, bytesLength, PNPCM_CONVERT);
    std::cout << "4.text after converting non-printing chars except line break:" << std::endl << strAfterConvertExceptLineBreack << std::endl << std::endl;
    std::string strAfterConvert = util.processBarcodeBytes(barcodeBytes, bytesLength, PNPCM_CONVERT, false);
    std::cout << "5.text after converting non-printing chars:" << std::endl << strAfterConvert << std::endl << std::endl;
    return 0;
}
mRouter.addResultReceiver(new CapturedResultReceiver() {
    @Override
    // Implement the callback method to receive DecodedBarcodesResult.
    // The method returns a DecodedBarcodesResult object that contains an array of BarcodeResultItems.
    // BarcodeResultItems is the basic unit from which you can get the basic info of the barcode like the barcode text and barcode format.
    public void onDecodedBarcodesReceived(DecodedBarcodesResult result) {
        process = new ProcessBarcodeResultUtil();
        if (result!=null && result.getItems().length!=0){
            for (int i=0; i< result.getItems().length; i++){
                // The return value is the modified barcode text.
                String processedResult = process.processBarcodeByte(result.getItems().getBytes(),ProcessBarcodeResultUtil.ProcessNonPrintingCharsMode.PNPCM_REMOVE,true);
                Log.i("ProcessByte", "onDecodedBarcodesReceived: processeResult = "+processedResult);
            }
        }
    }
});
// Create a ProcessBarcodeResultUtil class
public class ProcessBarcodeResultUtil {
    enum ProcessNonPrintingCharsMode{
        PNPCM_KEEP,
        PNPCM_REMOVE,
        PNPCM_CONVERT
    }
    final HashMap<Integer, String> charValueToStringDict = new HashMap<Integer, String>();
    ProcessBarcodeResultUtil(){
        final int[] NonPrintingAsciiCharsValue = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,127};
        final String[] NonPrintingAsciiCharsString = {
                "{NUL}","{SOH}","{STX}","{ETX}","{EOT}","{ENQ}","{ACK}","{BEL}","{BS}","{HT}","{LF}","{VT}","{FF}","{CR}","{SO}","{SI}",
                "{DLE}","{DC1}","{DC2}","{DC3}","{DC4}","{NAK}","{SYN}","{ETB}","{CAN}","{EM}","{SUB}","{ESC}","{FS}","{GS}","{RS}","{US}","{DEL}"
        };
        for (int i = 0; i < 33; ++i){
            charValueToStringDict.put(NonPrintingAsciiCharsValue[i], NonPrintingAsciiCharsString[i]);
        }
    }
    public String processBarcodeByte(byte[] barcodeByte, ProcessNonPrintingCharsMode mode, boolean keepLineBreak){
        StringBuilder processedResult = new StringBuilder();
        for (int i=0; i<barcodeByte.length; i++){
            int byteValue = (int)barcodeByte[i];
            if ((!charValueToStringDict.containsKey(byteValue)) || ((byteValue == 10 || byteValue == 13) && keepLineBreak) || mode == ProcessNonPrintingCharsMode.PNPCM_KEEP){
                processedResult.append((char)barcodeByte[i]);
            }
            else if(mode == ProcessNonPrintingCharsMode.PNPCM_CONVERT){
                processedResult.append(charValueToStringDict.get(byteValue));
            }
        }
        return processedResult.toString();
    }
}
typedef NS_ENUM(NSInteger,EnumResultProcessMode)
{
    RPM_KEEP = 0,
    RPM_CONVERT = 1,
    RPM_REMOVE = 2
};
...
- (void)onDecodedBarcodesReceived:(DSDecodedBarcodesResult *)result {
    if (result.items.count > 0) {
        for (DSBarcodeResultItem *item in result.items) {
            NSString *modifiedBarcodeText = [self processResult:item.bytes mode:RPM_CONVERT isBreaklineKept:NO];
            msgText = [msgText stringByAppendingString:[NSString stringWithFormat:@"\nFormat: %@\nText: %@\n", item.formatString, modifiedBarcodeText]];
        }
    }
}
- (NSString *)processBarcodeBytes:(NSData *)byte
                     mode:(EnumResultProcessMode)mode
          isBreaklineKept:(BOOL)isKept{
    NSArray<NSNumber*>* _nonPrintingAsciiCharsKey = @[@0,@1,@2,@3,@4,@5,@6,@7,@8,@9,@10,@11,@12,@13,@14,@15,@16,@17,@18,@19,@20,@21,@22,@23,@24,@25,@26,@27,@28,@29,@30,@31,@127];
    NSArray<NSString*>* _nonPrintingAsciiCharsString = @[@"{NUL}",@"{SOH}",@"{STX}",@"{ETX}",@"{EOT}",@"{ENQ}",@"{ACK}",@"{BEL}",@"{BS}",@"{HT}",@"{LF}",@"{VT}",@"{FF}",@"{CR}",@"{SO}",@"{SI}",@"{DLE}",@"{DC1}",@"{DC2}",@"{DC3}",@"{DC4}",@"{NAK}",@"{SYN}",@"{ETB}",@"{CAN}",@"{EM}",@"{SUB}",@"{ESC}",@"{FS}",@"{GS}",@"{RS}",@"{US}",@"{DEL}"];
    NSMapTable<NSNumber*,NSString *> * _charValueToStringDict = [NSMapTable strongToStrongObjectsMapTable];
    for (int i=0; i<_nonPrintingAsciiCharsKey.count;i++){
        [_charValueToStringDict setObject:_nonPrintingAsciiCharsString[i] forKey:_nonPrintingAsciiCharsKey[i]];
    }
    const char* _Nonnull barcodeByteChar = byte.bytes;
    NSString *processedText = @"";
    for (int i=0;i<byte.length;i++){
        if ((isKept && (barcodeByteChar[i]==10 || barcodeByteChar[i]==13)) || mode==RPM_KEEP || ((int)barcodeByteChar[i]>31 && (int)barcodeByteChar[i]!=127 && (int)barcodeByteChar[i]!=0)){
            NSString *nextString = [NSString stringWithFormat:@"%c",barcodeByteChar[i]];
            processedText = [processedText stringByAppendingString:nextString];
        }
        else if (mode == RPM_CONVERT){
            NSNumber *keyValue = [[NSNumber alloc] initWithInt:(int)barcodeByteChar[i]];
            NSString *nextString = [_charValueToStringDict objectForKey:@2];
            processedText = [processedText stringByAppendingString:nextString];
        }
    }
    return processedText;
}
enum EnumResultProcessMode{
    case keep
    case convert
    case remove
}
func onDecodedBarcodesReceived(_ result: DecodedBarcodesResult) {
    if let items = result.items, items.count > 0 {
        for item in items {
            let processedBarcodeText = processBarcodeBytes(byte: item.bytes, processMode: EnumResultProcessMode.convert, isKeep: true)
            item.barcodeText = processedBarcodeText
        }
    }
}
private func processBarcodeBytes(byte:Data, processMode:EnumResultProcessMode, isKeep:Bool) -> String{
    let charValueToStringDict:NSDictionary = [0:"{NUL}",1:"{SOH}",2:"{STX}",3:"{ETX}",4:"{EOT}",5:"{ENQ}",6:"{ACK}",7:"{BEL}",8:"{BS}",9:"{HT}",10:"{LF}",11:"{VT}",12:"{FF}",13:"{CR}",14:"{SO}",15:"{SI}",16:"{DLE}",17:"{DC1}",18:"{DC2}",19:"{DC3}",20:"{DC4}",21:"{NAK}",22:"{SYN}",23:"{ETB}",24:"{CAN}",25:"{EM}",26:"{SUB}",27:"{ESC}",28:"{FS}",29:"{GS}",30:"{RS}",31:"{US}",127:"{DEL}"]
    var processedString = ""
    for i in 0...byte.count-1{
        if ((isKeep && ((byte[i]==10) || (byte[i]==13))) || (processMode == EnumResultProcessMode.keep) || ((byte[i]>31) && (byte[i] != 127) && (byte[i] != 0))){
            let nextText:String = String(bytes: [byte[i]], encoding: String.Encoding.utf8)!
            processedString += nextText as String
        }
        else if (processMode == EnumResultProcessMode.convert){
            let nextText:NSString = charValueToStringDict.object(forKey: byte[i]) as! NSString
            processedString += nextText as String
        }
    }
    return processedString
}

This page is compatible for:

Version 7.5.0

Is this page helpful?

YesYes NoNo

latest version

  • Latest version
  • Version 10.x
    • Version 10.2.0
    • Version 10.0.21
    • Version 10.0.20
    • Version 10.0.10
    • Version 10.0.0
  • Version 9.x
    • Version 9.6.40
    • Version 9.6.33
    • Version 9.6.32
    • Version 9.6.31
    • Version 9.6.30
    • Version 9.6.20
    • Version 9.6.10
    • Version 9.6.0
    • Version 9.4.0
    • Version 9.2.0
    • Version 9.0.0
  • Version 8.x
    • Version 8.8.0
    • Version 8.6.0
    • Version 8.4.0
    • Version 8.2.0
    • Version 8.1.2
    • Version 8.1.0
    • Version 8.0.0
  • Version 7.x
    • Version 7.6.0
    • Version 7.5.0
Change +