View previous topic :: View next topic
|
Author |
Message |
Apurva Ghogale
New User
Joined: 20 Sep 2018 Posts: 9 Location: INDIA
|
|
|
|
Hi ,
I want to UNSTRING a big string of data approximately 12,60,000(max) in length.And after unstringing the data I need to write each unstrung record (ws-data) to one row in output file. Each record can be of 700 bytes.The input string can vary ,sometimes we can get less data as well from other systems,but we are considering the maximum possible data.
Please suggest the best coding practise or alternative to below approach as if I use the below I need to code WS-DATA from 1 t0 1800 times and may end up in untidy code.
UNSTRING WS-REQUEST DELIMITED BY "|"
INTO WS-DATA1
WS-DATA2
WS-DATA3
WS-DATA4
.
.
.
WS-DATA 1800.
Thanks,
Apurva |
|
Back to top |
|
|
expat
Global Moderator
Joined: 14 Mar 2007 Posts: 8796 Location: Welsh Wales
|
|
|
|
Hi, and welcome to the forum.
Please take a look at the difference between what you have posted and how it looks after I have amended your post using the code tags. They are really easy to use.
Manual code - do this
Code: |
[code]Your stuff
goes in between
the tags[/code] |
Or - highlight the code that you want to show and simply click the Code box above the text entry box
Apurva Ghogale wrote: |
Hi ,
I want to UNSTRING a big string of data approximately 12,60,000(max) in length.And after unstringing the data I need to write each unstrung record (ws-data) to one row in output file. Each record can be of 700 bytes.The input string can vary ,sometimes we can get less data as well from other systems,but we are considering the maximum possible data.
Please suggest the best coding practise or alternative to below approach as if I use the below I need to code WS-DATA from 1 t0 1800 times and may end up in untidy code.
Code: |
UNSTRING WS-REQUEST DELIMITED BY "|"
INTO WS-DATA1
WS-DATA2
WS-DATA3
WS-DATA4
.
.
.
WS-DATA 1800.
|
Thanks,
Apurva |
|
|
Back to top |
|
|
Nic Clouston
Global Moderator
Joined: 10 May 2007 Posts: 2454 Location: Hampshire, UK
|
|
|
|
Why not try parsing in a loop: find the first delimiter, use reference modification to save the leading part into a table, remove that part from the string and repeat. |
|
Back to top |
|
|
Apurva Ghogale
New User
Joined: 20 Sep 2018 Posts: 9 Location: INDIA
|
|
|
|
How to remove that part from the string? I m really not sure how to achieve this?
Can you paste the code for that? |
|
Back to top |
|
|
Nic Clouston
Global Moderator
Joined: 10 May 2007 Posts: 2454 Location: Hampshire, UK
|
|
|
|
you simply read along the string, using reference modification to read each byte, to find your delimiter counting each byt along the way. you now know the length of the first part so you can save it using reference modification (1:lengthOfPart - 1) and move the remainder (lengthOfPart + 1: ) to a temp variable (or replace the current string).
Example code (from a similar topic on another forum, this week)
Code: |
01 WS-INPUT PIC X(20) VALUE 'My|very|long|string'.
01 WS-SUB PIC 9(4) COMP.
01 WS-SUB1 PIC 9(4) COMP VALUE 0.
01 WS-START1 PIC 9(4) COMP VALUE 1.
01 WS-INDEX PIC 9(4) COMP VALUE 0.
01 WS-ARRAY PIC X(10) OCCURS 0 TO 9999 DEPENDING ON WS-INDEX.
PROCEDURE DIVISION.
PERFORM VARYING WS-SUB
FROM 1 BY 1
UNTIL WS-SUB > FUNCTION LENGTH(WS-INPUT)
COMPUTE WS-SUB1 = WS-SUB1 + 1
IF WS-INPUT(WS-SUB:1) = ";"
ADD 1 TO WS-INDEX
MOVE WS-INPUT(WS-START1:WS-SUB1 - 1)
TO WS-ARRAY(WS-INDEX)
MOVE 0 TO WS-SUB1
COMPUTE
WS-START1 = WS-SUB + 1
END-COMPUTE
END-IF
IF WS-SUB EQUAL FUNCTION LENGTH(WS-INPUT)
ADD 1 TO WS-INDEX
MOVE WS-INPUT(WS-START1:WS-SUB1)
TO WS-ARRAY(WS-INDEX)
END-IF
END-PERFORM
|
|
|
Back to top |
|
|
Apurva Ghogale
New User
Joined: 20 Sep 2018 Posts: 9 Location: INDIA
|
|
|
|
Thank you Nic for the solution. I will try it and let you know once it works. |
|
Back to top |
|
|
Rohit Umarjikar
Global Moderator
Joined: 21 Sep 2010 Posts: 3076 Location: NYC,USA
|
|
|
|
Welcome!
At least , I am not sure of the loop but
Code: |
IF WS-INPUT(WS-SUB:1) = ";" |
should be
Code: |
IF WS-INPUT(WS-SUB:1) = "|" |
But why do you have a problem with COBOL UNSTRING ?
Read more about UNSTRING and POINTER concepts and you do a Unstring into an array of 1800 or whatever occurrences you want. May be you only need 5 lines of code to get what you want.
Example: UNSTRING statement
Refer how its being implemented by others in past.
ibmmainframes.com/about56116.html
ibmmainframes.com/about65202.html |
|
Back to top |
|
|
Nic Clouston
Global Moderator
Joined: 10 May 2007 Posts: 2454 Location: Hampshire, UK
|
|
|
|
The code was taken from a response to a similar problem, posted in another forum, where the delimiter was ';'. I thought I had changed it but this is also an exercise for the TS. |
|
Back to top |
|
|
Rohit Umarjikar
Global Moderator
Joined: 21 Sep 2010 Posts: 3076 Location: NYC,USA
|
|
|
|
Yes Nic, that does without saying |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
Quote: |
The input string can vary ,sometimes we can get less data as well from other systems,but we are considering the maximum possible data. |
If the "less data" in your post means you may not get all 1800 delimiters, then UNSTRING is probably not your best option. There is no compiler limit to prevent you from coding up all 1800 INTO variables, but you would need the POINTER and TALLYING variables to determine how far you got when the ON OVERFLOW condition was hit (and if you have less than 1800 delimiters, you will hit the ON OVERFLOW condition).
Also, how are you building your big string (since I know you cannot read it into your program as a single record)? Perhaps it would be better to split out the records there instead of after assembling it into a big string? |
|
Back to top |
|
|
sergeyken
Senior Member
Joined: 29 Apr 2008 Posts: 2135 Location: USA
|
|
|
|
Just a note.
UNSTRING had been introduced in COBOL mainly to avoid very bad performance when one-by-one character scan is implemented as COBOL loop.
It's not good idea to return back from UNSTRING to a primitive loop.
It resembles a stone hammer used to build a skyscraper... |
|
Back to top |
|
|
Apurva Ghogale
New User
Joined: 20 Sep 2018 Posts: 9 Location: INDIA
|
|
|
|
Hi Rohit/Robert,
The string is coming from other application and they are not ready to split it. Hence they will be sending the whole data in a string only. There is no problem as to use 1800 variables but m not sure what will actually happen if data goes till actual 1800 variables. hence I was looking for some alternative where I can avoid defining 1800 variables.
Hi Robert,
If there is less data than 1800 ,how will ON OVERFLOW will hit? It wont hit right. IT will hit when it goes beyong 1800 ? M I right? So anyways I will have to define maximum possible delimiters. |
|
Back to top |
|
|
Nic Clouston
Global Moderator
Joined: 10 May 2007 Posts: 2454 Location: Hampshire, UK
|
|
|
|
The word is 'Am' not 'M'.
Why do you not try with a simple test of three or four tokens in a string? |
|
Back to top |
|
|
Apurva Ghogale
New User
Joined: 20 Sep 2018 Posts: 9 Location: INDIA
|
|
|
|
Hi Nic,
Yes I have executed the below code suggested by you with few modification and is working fine except the last record is not getting populated. I am looking into it.
Code: |
PERFORM VARYING W10-SUB FROM 1 BY 1
UNTIL W10-SUB > FUNCTION LENGTH(WCF-RECORD)
OR W20-EOF
COMPUTE W10-SUB1 = W10-SUB1 + 1
IF (W10-SUB + 10) NOT GREATER THAN
FUNCTION LENGTH(WCF-RECORD)
IF WCF-RECORD(W10-SUB:10) = 'XXXXXXXXXX'
DISPLAY 'MATCH'
ADD 1 TO W10-INDEX
MOVE WCF-RECORD(W10-START:(W10-SUB1)- 1) TO
W10-ARRAY(W10-INDEX)
MOVE 0 TO W10-SUB1
COMPUTE W10-START = W10-SUB + 1
END-IF
IF W10-SUB EQUAL FUNCTION LENGTH(WCF-RECORD)
ADD 1 TO W10-INDEX
MOVE WCF-RECORD(W10-START:W10-SUB1) TO
W10-ARRAY(W10-INDEX)
SET W20-EOF TO TRUE
END-IF
ELSE
SET W20-EOF TO TRUE
END-IF
END-PERFORM.
|
|
|
Back to top |
|
|
Rohit Umarjikar
Global Moderator
Joined: 21 Sep 2010 Posts: 3076 Location: NYC,USA
|
|
|
|
Do you know there is depending upon clause in an array? So tally all your pipes in a string and assign that to the array before Unsteing and this is already suggested by Robert. No array fails if the size goes beyond 1800.
ON OVERFLOW phrases |
|
Back to top |
|
|
Rohit Umarjikar
Global Moderator
Joined: 21 Sep 2010 Posts: 3076 Location: NYC,USA
|
|
|
|
Deleted |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
Quote: |
If there is less data than 1800 ,how will ON OVERFLOW will hit? It wont hit right. IT will hit when it goes beyong 1800 ? M I right? So anyways I will have to define maximum possible delimiters. |
I tested UNSTRING on my COBOL 5.1 system, and if there are fewer fields than you UNSTRING into, ON OVERFLOW is invoked and POINTER is set to the first byte not placed in a variable, and TALLY has the number of fields processed. If you have more fields than you UNSTRING into, ON OVERFLOW is invoked with the same usage for POINTER and TALLY. In both cases, the variables that UNSTRING used as targets do have the correct data in them. So if you want to use UNSTRING, you'll have to carefully consider how to use ON OVERFLOW since it will be invoked unless the number of fields match exactly what you code. And another thing to consider -- with UNSTRING, the last field in the string must be terminated with a delimiter or it will contain however many characters were left in the big string (be that 1 or 1,000,000 bytes). |
|
Back to top |
|
|
|