Solved

Reading variable length EBCDIC in SAS

Posted on 2016-08-24
9
139 Views
Last Modified: 2016-09-07
I am trying to read an incoming mainframe file that contains a variable length field that contains EBCDIC data.

To read this field, I am currently using $VARYING informat, but this is only suitable for reading variable length ASCII fields. What I am looking for is an informat that reads a variable length field AND converts to readable format in the output.

Here is my code :-

			/* P31 - NAME_LINE_1 */
			if Bitmap_1a='..............................1.'B then
			do;
				input
				b_ADDESS_LINE_1_len $370FIB2.
				b_ADDESS_LINE_1 $VARYING23. b_ADDESS_LINE_1_len
				@;
				data_length = data_length - b_NAME_LINE_1_len - 2;
			end;

Open in new window


The problem with the above code is that it populates the output with the EBCDIC, but I need the variable field converting to ASCII. Is there a way to convert a variable length field from EBCDIC to ASCII without relying on the informat / format statements?
0
Comment
Question by:Martin r
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
  • 2
  • +1
9 Comments
 
LVL 19

Expert Comment

by:Thommy
ID: 41768962
You should read the book Reading External Data Files Using SAS: Examples Handbook

Check the table of contents. There are a lot of examples including reading EBCDIC data...
0
 
LVL 19

Expert Comment

by:Thommy
ID: 41768989
And also check this from SAS Knowledge Base...
Reading EBCDIC Files on ASCII Systems
0
 

Author Comment

by:Martin r
ID: 41769050
Thanks for the comments Thommy, but I have already looked at the recommended documentation online, and this is really a last resort for me - as there is nothing anywhere that indicates SAS is actually capable of reading variable length EBCDIC informats. In fact, I don't think it is....:-|

I have no difficulty reading  fixed-length EBCDIC fields, as well as the binary fields that specify the record-length and segment-length - this is all working. It's just there is no INFORMAT that will allow me to read and convert EBCDIC to ASCII for a variable length field.

I did just have a thought though - I could read the field as "FIXED EBCDIC" and then reset the pointer back to the correct position according to the value of the b_ADDESS_LINE_1_len field. It would only be a simple matter of chopping the surplus data from the end of the field.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 8

Accepted Solution

by:
ShannonEE earned 500 total points
ID: 41774240
Even better would be -

		/* P31 - NAME_LINE_1 */
			if Bitmap_1a='..............................1.'B then
			do;
				input
				b_ADDESS_LINE_1_len $370FIB2.
				b_ADDESS_LINE_EBCDIC $VARYING23. b_ADDESS_LINE_1_len
				@;
				data_length = data_length - b_NAME_LINE_1_len - 2;
				b_ADDESS_LINE_1 = inputc(b_ADDRESS_LINE_EBCDIC,  $EBCDIC. b_ADDRESS_LINE_1_len);
			end;

Open in new window


Note that you need to specify both a type ( $ ) and max width for both

b_ADDESS_LINE_1  and
b_ADDRESS_LINE_EBCDIC

Failure to specify a width can lead to very mysterious run time problems.

Maybe that max length is 23 as you have on the $VARYING informat, but it is best also to have a statement

length   b_ADDESS_LINE_1  b_ADDRESS_LINE_EBCDIC $ 23;

Open in new window


This does the varying field length issue in the input statement and then uses the INPUTC function to do the conversion from EBCDIC.

Regards,

Ian
1
 
LVL 16

Expert Comment

by:theo kouwenhoven
ID: 41785907
Hi Martin,

I don't know if this will help, but normally the Ebcdic to Ascii translation will be automatically don by the DB-driver, unless it's Binary-data (Bitmap).
The Varlength fields in a DB2 database has the first 2-positions filled with the length of the data.
0
 

Author Closing Comment

by:Martin r
ID: 41786506
Thanks ShannonEE!

The solution is exactly what I was after. The solution ShannonEE provided is for RUNTIME FUNCTION to allow conversion during the loop.

http://support.sas.com/kb/50/013.html

I have managed to convert the variable length field now so can ensure the output is all formatted in ASCII. The final code was as follows :-

                  /* P31 - REFERENCIA DEL ADQUIRENTE */
                  if Bitmap_1a='..............................1.'B then
                  do;
                        input
                        b_acquirer_reference_len $EBCDIC2.
                        b_acquirer_reference_ebcdic $VARYING23. b_acquirer_reference_len
                        @;
                        data_length = data_length - b_acquirer_reference_len - 2;
                        b_acquirer_reference_ascii = inputc(b_acquirer_reference_ebcdic, "$EBCDIC23.");
                  end;

Thanks all for your help!!
0
 

Author Comment

by:Martin r
ID: 41786528
****UPDATED****

The above solution worked, but produced excessive notes due to specifying the maximum length for format. Therefore I used a concatenation to enable the length variable to be used in the format construction. The final code was as follows :-

                  /* P31 - REFERENCIA DEL ADQUIRENTE */
                  if Bitmap_1a='..............................1.'B then
                  do;
                        length b_acquirer_reference_ebcdic b_acquirer_reference_ascii $ 23;
                        input
                        b_acquirer_reference_len $EBCDIC2.
                        b_acquirer_reference_ebcdic $VARYING23. b_acquirer_reference_len
                        @;
                        data_length = data_length - b_acquirer_reference_len - 2;
                        b_acquirer_reference_ascii = inputc(b_acquirer_reference_ebcdic, "$EBCDIC" || b_acquirer_reference_len || "." );
                  end;
0
 
LVL 8

Expert Comment

by:ShannonEE
ID: 41787032
Martinr,

The posted code missed a comma.  With the INPUTC  function sas makes the format up at run time (which you did), but if you specify the 3rd parameter (which I attempted to do) then it should construct the format without any NOTES or WARNINGS.  As in

		b_ADDESS_LINE_1 = inputc(b_ADDRESS_LINE_EBCDIC,  $EBCDIC.   ,   b_ADDRESS_LINE_1_len);

Open in new window


(A comma after $EBCDIC and before b_ADDRESS_LINE_1_LEN  was missing)
I didn't test out the code because currently I don't have access to a mainframe to write test data and the code is quite specific to your situation.

As an aside, note that on the mainframe the record format and length is specified in the DCB and (from what I remember) includes F, FB, V, VB, VBA, D, DB, U, (and probably a host of other formats).  Obtaining the record length will be different for each record format.

In your case it appears that the field length is in another field within the record and so getting the record length from the data structure as read in an ASCII environment will be useless for inputting the variable length field that you need to do here.
1
 

Author Comment

by:Martin r
ID: 41787331
Thanks ShannonEE, that's a neater expression. I should point out that I am using SAS Enterprise Guide (Windows) - hence requiring the output in ASCII; so I have to specify the format in quotes.

/* P31 - REFERENCIA DEL ADQUIRENTE */
if Bitmap_1a='..............................1.'B then
do;
	length b_acquirer_reference_ebcdic b_acquirer_reference_ascii $ 23;
	input
	b_acquirer_reference_len $EBCDIC2.
	b_acquirer_reference_ebcdic $VARYING23. b_acquirer_reference_len
	@;
	data_length = data_length - b_acquirer_reference_len - 2;
	b_acquirer_reference_ascii = inputc(b_acquirer_reference_ebcdic, "$EBCDIC." , b_acquirer_reference_len);
end;

Open in new window

0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Best CRM to customize - Free / less fee 2 44
Advice on a batch file that copies, moves, sftp's & deletes files 6 37
FSRREMOS 7 60
PowerShell and cisco ios 3 46
If you get continual lockouts after changing your Active Directory password, there are several possible reasons.  Two of the most common are using other devices to access your email and stored passwords in the credential manager of windows.
The Windows functions GetTickCount and timeGetTime retrieve the number of milliseconds since the system was started. However, the value is stored in a DWORD, which means that it wraps around to zero every 49.7 days. This article shows how to solve t…
Saved searches can save you time by quickly referencing commonly searched terms on any topic. Whether you are looking for questions you can answer or hoping to learn about a specific issue, a saved search can help you get the most out of your time o…

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question