Dev Center
Table of contents

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:

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.42
    • 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
  • Documentation Homepage
Change +