Do not input private or sensitive data. View Qlik Privacy & Cookie Policy.
Skip to main content

Announcements
Save $650 on Qlik Connect, Dec 1 - 7, our lowest price of the year. Register with code CYBERWEEK: Register
cancel
Showing results for 
Search instead for 
Did you mean: 
Anonymous
Not applicable

[resolved] Packed Decimals

Hello,
I have a positional file with some fields being in Packed Decimal format. I have successfully ceated possitional file schema. How do I convert values that are in Packed decimal format to regular decimals? Also i saw something about tFileInputEBCDIC component but i can't find it in my studio. Could anyone give me any suggestions?
Thank you
Labels (2)
1 Solution

Accepted Solutions
Anonymous
Not applicable
Author

This is resolved now the solution was:
    Create a positional file in the repository where the columns of Packed decimals are of type byte[]
    Create routine ParsePackedDecimal with a method parse to convert byte[] packed decimal to long integer.
    Method  :
public static long parse(byte[] pdIn) throws Exception {
      // Convert packed decimal to long
        final int PlusSign = 0x0C;       // Plus sign
        final int MinusSign = 0x0D;      // Minus
        final int NoSign = 0x0F;         // Unsigned
        final int DropHO = 0xFF;         // AND mask to drop HO sign bits
        final int GetLO  = 0x0F;         // Get only LO digit
  long val = 0;                    // Value to return
   
        for(int i=0; i < pdIn.length; i++) {
           int aByte = pdIn & DropHO; // Get next 2 digits & drop sign bits
           if(i == pdIn.length - 1) {    // last digit?
              int digit = aByte >> 4;    // First get digit
              val = val*10 + digit;
//               System.out.println("digit=" + digit + ", val=" + val);
              int sign = aByte & GetLO;  // now get sign
              if (sign == MinusSign)
                 val = -val;
              else {
                 // Do we care if there is an invalid sign?
                 if(sign != PlusSign && sign != NoSign)
                    throw new Exception("OC7");
              }
           }else {
              int digit = aByte >> 4;    // HO first  
              val = val*10 + digit;
//               System.out.println("digit=" + digit + ", val=" + val);
              digit = aByte & GetLO;      // now LO
              val = val*10 + digit;
//               System.out.println("digit=" + digit + ", val=" + val);
           }
        }
  return val;
  } // end parse()

3. Connect tFileInputPositional (In Basic settings check the box "Use byte length as the cardinality" and in Advanced settings uncheck the box "Trim all columns") to TXMLMap and tXMLMap to tfileOutputDElimited or any other format you want to use.  In the mapping,  expressions tool needs to be used to transform packed decimal to its string representation:
Expression to convert packed decimal from byte[] to long:
ParsePackedDecimal.parse(YourRow.YourColumnName)
My example:
ParsePackedDecimal.parse(row9.DLY_DRAFT_AMT)
Then we need to convert this long integer value to our desired decimal precision in the next expression:
Numeric.convertString2BigDecimal("9(7)V99",String.valueOf(Var.Var1)).toString()
There is function  Numeric.convertImpliedDecimalFormat, but it should not be used as it is losing precision.
4. Var.Var2 is your parsed and formatted packed decimal as a string and ready to be written to xML or other file.

View solution in original post

6 Replies
Anonymous
Not applicable
Author

Hi,
The EBCDIC components have been deprecated several version ago to be replaced by Talend Data Mapper.
The old components have been published on Talend Exchange and are provided as is, without support from Talend for version 6.0+.
https://exchange.talend.com/
Best regards
Sabrina
Anonymous
Not applicable
Author

Hello, Thank you for the reply,
I now have the file schema, and only a few fields are in S9(7)V99 or similar formats, is there any simple way to tell talend to treat those fields as such? It gives me null if I just set it as BigDecimal.
Anonymous
Not applicable
Author

Hi,
Could you please elaborate your case with an example with input and expected output values?
Best regards
Sabrina
Anonymous
Not applicable
Author

I have a positional file with rows like that - packed decimals are not showing :
C910124141094141090011604263N1AB7AP0GL655147 fþ16042616SENTRA 1.8 S CV160426DF BDSALSENTR    
C542134136294136290011604263N1AB7AP4GL653515 Ÿ^16042616SENTRA 1.8 S CV160426DF BDSALSENTR    
C910124141174141170011604263N1AB7AP5GL654981 fþ16042616SENTRA 1.8 S CV160426DF BDSALSENTR    
C521124136334136330011604263N1AB7AP7GL656523 16042616SENTRA 1.8SV  C160426DF ¬øBDSALSENTR     with the output format similar to:
C--52112---413633---413633---001---160426---3N1AB7AP7GL656523---(some S9(7)V99 format number) ---160426---16---SENTRA 1.8SV  C--160426--DF--(some S9(7)V99 format number)--BDSALSENTR
I made metadata for the positional file, but how to parse those S9(7)V99 numbers?
Is there any function I could use?
Anonymous
Not applicable
Author

This is resolved now the solution was:
    Create a positional file in the repository where the columns of Packed decimals are of type byte[]
    Create routine ParsePackedDecimal with a method parse to convert byte[] packed decimal to long integer.
    Method  :
public static long parse(byte[] pdIn) throws Exception {
      // Convert packed decimal to long
        final int PlusSign = 0x0C;       // Plus sign
        final int MinusSign = 0x0D;      // Minus
        final int NoSign = 0x0F;         // Unsigned
        final int DropHO = 0xFF;         // AND mask to drop HO sign bits
        final int GetLO  = 0x0F;         // Get only LO digit
  long val = 0;                    // Value to return
   
        for(int i=0; i < pdIn.length; i++) {
           int aByte = pdIn & DropHO; // Get next 2 digits & drop sign bits
           if(i == pdIn.length - 1) {    // last digit?
              int digit = aByte >> 4;    // First get digit
              val = val*10 + digit;
//               System.out.println("digit=" + digit + ", val=" + val);
              int sign = aByte & GetLO;  // now get sign
              if (sign == MinusSign)
                 val = -val;
              else {
                 // Do we care if there is an invalid sign?
                 if(sign != PlusSign && sign != NoSign)
                    throw new Exception("OC7");
              }
           }else {
              int digit = aByte >> 4;    // HO first  
              val = val*10 + digit;
//               System.out.println("digit=" + digit + ", val=" + val);
              digit = aByte & GetLO;      // now LO
              val = val*10 + digit;
//               System.out.println("digit=" + digit + ", val=" + val);
           }
        }
  return val;
  } // end parse()

3. Connect tFileInputPositional (In Basic settings check the box "Use byte length as the cardinality" and in Advanced settings uncheck the box "Trim all columns") to TXMLMap and tXMLMap to tfileOutputDElimited or any other format you want to use.  In the mapping,  expressions tool needs to be used to transform packed decimal to its string representation:
Expression to convert packed decimal from byte[] to long:
ParsePackedDecimal.parse(YourRow.YourColumnName)
My example:
ParsePackedDecimal.parse(row9.DLY_DRAFT_AMT)
Then we need to convert this long integer value to our desired decimal precision in the next expression:
Numeric.convertString2BigDecimal("9(7)V99",String.valueOf(Var.Var1)).toString()
There is function  Numeric.convertImpliedDecimalFormat, but it should not be used as it is losing precision.
4. Var.Var2 is your parsed and formatted packed decimal as a string and ready to be written to xML or other file.
Anonymous
Not applicable
Author

Hi,
Great it is fixed. Thanks for your solution.
Best regards
Sabrina