WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Binary Functions

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Binary Sorting of a String in a Buffer

Keywords:    binarysort binarypeekstr

Question:

I'm trying to sort a string on the fly in the middle of my program. I am using the BinarySort function to sort it. The method I am using is to poke the string to a temporary buffer, sort the buffer, and then peek the string out of the buffer. The last part is the one that is giving me problems. I can write the sorted buffer to a file and everything is fine but trying to use BinaryPeekStr to grab out the data is only resulting in a null string. Is there an easier way to do this or am I going to have to throw the output to a file and then read the file into a string?

Answer:

  1. BinarySort sorts fixed sized records. You have to stuff each word into its own fixed size portion of the buffer.

  2. BinarySort sorts the *entire* buffer. So it the buffer is big, oftimes the first part is just a bunch of zeros. You have to fish around to find the data. BinaryIndex(bb,0,"",@fwdscan) will locate the first non-null character in the buffer.

  3. If, for debugging, you BinaryWrite the buffer to a file and look at it with a hex editor (or right click the file and open with Browser and select hex dump mode) you can see it. (Hint. If your fixed size records in the binary buffer is some multiple of 16 then it's a lot easier to view it with a hex viewer)

  4. If the string is not too long (say maybe 5000 characters or less, then maybe look at the ItemSort function).

A Related Question:

I'm having a very frustrating problem with the BINARYSORT function.

The basic steps of my WinBatch are as follows:

  1. Take a variable length record TEXT file.
  2. Extract portions of that same file and build FIXED (50 Character) length records to another file.
  3. Allocate a Binary Buffer of a size equal to the file created in step 2.
  4. Read the file from step 2 into the binary buffer.
  5. Sort the binary buffer {BinarySort(FB1, 50, 0, 30, @STRING|@ASCENDING)}
  6. Write the Binary Buffer out to another file.
The problem is that the file generated in step 6 is corrupt. Portions of the data are gone, the file now appears to have variable length records again.

It seems that the BinarySort Function is the problem since I can do all of the above EXCEPT for step 5 (the sort) and the output file of step 6 is identical to the file from step 4. It also doesn't matter if I just run the .WBT file or compile it.

I've Tried using STRFIX, STRFIXL., STRFIXCHARS and STRFIXCHARSL,; The FILE I'm creating is fixed length records when I check it with a text editor.

;================Here's a snippet of code=====================

DLen	 = 50

If DirExist (strcat(NTBDsk,"\Temp")) == @FALSE Then DirMake (strcat(NTBDsk,"\Temp"))
;; Ask User for Date to Use
Dt1 = AskLine("DAILY ACCOUNTING", "Enter Date (MMDDYYYY) to Process",
"")
MM = StrSub(Dt1, 1, 2)
DD = StrSub(Dt1, 3, 2)
YY = StrSub(Dt1, 5, 4)
Date = StrCat(MM, "-", DD, "-", YY)
;; Build FileNames to Use
Inf1 = StrCat(Drv,"\Logs\", Dt1, ".Log")
Tmp1 = StrCat(NTBDsk,"\Temp\", Dt1, ".Wr1")
Tmp2 = StrCat(NTBDsk,"\Temp\", Dt1, ".Wr2")
Tmp3 = StrCat(NTBDsk,"\Temp\", Dt1, ".Wr3")
Out1 = StrCat(Dt1, ".Dly")
;; Process the Input File
FileCopy(Inf1, Tmp1, @FALSE)
Inf1 = FileOpen(Tmp1, "READ")
Out1 = FileOpen(Tmp2, "APPEND")
While @TRUE
  InLn1 = FileRead(Inf1)
   If InLn1 == "*EOF*" Then Break
    InLn1 = StrReplace(InLn1, ",", "|")
      If ItemCount(InLn1, "|") <9 Then Continue
      If StrLen(InLn1) < 46 Then Continue
     I1 = ItemExtract(1, InLn1, "|")
      CurShr = StrFixChars(I1, " ", 30)
     I2 = ItemExtract(4, InLn1, "|")
      LCode  = StrFixChars(I2, " ", 1)
     I3 = ItemExtract(5, InLn1, "|")
      CurUse = StrFixCharsL(I3, " ", 5)
     I4 = ItemExtract(6, InLn1, "|")
      Lmt  = StrFixCharsL(I4, " ", 14)
    OutLn1 = StrFixChars(StrCat(CurShr, LCode, CurUse,Lmt), " ", DLen)
 FileWrite(Out1,OutLn1)
EndWhile
FileClose(Inf1)
FileClose(Out1)
SF1 = FileSize(Tmp2)
FB1 = BinaryAlloc(SF1)
BinaryRead(FB1, Tmp2)
Delay(1)
BinarySort(FB1, DLen, 0, 30, @STRING)
Delay(1)
BinaryWrite(FB1, Tmp3)

;;;;; Leave at this point since the data is now corrupt after the sort

EXIT


Answer:

<<<<<<<<<< I think the answer is #2 >>>>>>>>>>>>>
  1. If we can get a copy of the Tmp2 file then we can run the following code (which looks perfectly ok) and see the problem ourselves
    tmp2="c:\temp\thefile.xxx"
    tmp3="c:\temp\thefile.yyy"
    SF1 = FileSize(tmp2)	 
    FB1 = BinaryAlloc(SF1)
    BinaryRead(FB1, Tmp2)
    Delay(1)
    BinarySort(FB1, 50, 0, 30, @STRING)
    Delay(1)
    BinaryWrite(FB1, Tmp3)
    

  2. Actually the real problem looks like the DLEN variable. It's set to 50 - which is the length of the string - but the FileWrite automagically adds 2 characters to the end of the file, so the real record length is 52.

    Sorting it with a record size of 50 would cause great problems. The resultant file would appear corrupted, because your cursor would be stepping through the file working with the 50 fixed character length, but getting off-sync when it steps over the CRLFs (which you didn't account for in your recsize).


Another BinarySort Question:

I'm using BinarySort() to sort some records that I've poked into RAM. Descending sort is working fine; ascending sort looks like it's wiping my allocated memory. Whenever I peek at my memory after a descending sort, everything looks fine, but after an ascending sort WIL returns null strings.

Is this a bug? If so, where do I download the patch?

Answer:

Not a bug. (Bugs are *real* hard to find.)

Basically it is sorting using the entire allocated buffer, and all you data moved up to the top of the buffer, and all the nulls are down below.

There are two ways to deal with it:

  1. BinaryIndex(bb,0,"",@fwdscan) will (If I recall correctly) locate the first non-null character for you, and then a little modulo arithmetic can find the beginning of your record.

  2. Alternatively I allocate yet another binary buffer of the exact size required, copy the data to it and sort that. That way null records do not get involved.

Another BinarySort Question:

The Binary Sort function is not sorting as I would expect it to, when I specify the key type @WORD1. I am specifying recsize=3, keyoffset=0 and keysize=3. However when I specify the keytype @STRING (which is default) input is sorted correctly....
Input:			012121003010011
Desired result:		003010011012121
BinarySort result:	012003010011121
the desired result and the result which is returned by the BinarySort function.

Running the script below, shows the problem

input='012121003010011'
Length=StrLen(input)
binbuf=BinaryAlloc(Length)
for i=1 to Length
number=StrSub(input,i,1)
BinaryPoke(binbuf,i-1,number)
next
; how to sort binbuf ? No
; flag "Sort Direction | Key Type"
; yields a sorted buffer !
sort_sequence=@ASCENDING
BinarySort(binbuf,3,0,3,sort_sequence | @WORD1)
byte_result=""
for i=0 to Length-1
byte_result=StrCat(byte_result,BinaryPeek(binbuf,i))
next
BinaryFree(binbuf)
;
; as a string, input is sorted correctly:
;
binbuf=BinaryAlloc(Length)
BinaryPokeStr(binbuf,0,input)
BinarySort(binbuf,3,0,3,sort_sequence)
string_result=BinaryPeekStr(binbuf,0,BinaryEodGet(binbuf))
BinaryFree(binbuf)
;
; Report on Sorted buffer below.
;
result_text=StrCat("Input was ",@TAB,input,@CRLF,"Result should be: ",@TAB,string_result,@CRLF,"Result is: ",@TAB,@TAB,byte_result)
if sort_sequence==@ASCENDING then sort_sequence="ASCENDING"
else sort_sequence="DESCENDING"
Message(StrCat("Results. Sort Sequence: ",sort_sequence),result_text)
exit 

I am running WinBatch Version - 2002A. What is the problem?

Answer

??? !!! ???

I can see what you want to do, but there are several issues with the approach. A datatype of WORD1 is a single 8 bit byte. But you are trying to sort 3 bytes with it. Not going to work. You maybe need 3 sorts to get it.

In addition a 3 byte field is not a native machine numeric data type. You can have 1, 2 or 4 byte numbers. And to further confuse the issue the bytes have to be placed in the buffer in the Intel numeric format (ummm low byte first)

Maybe you do really just want a string sort.


Article ID:   W12728
Filename:   BinarySort Considerations.txt
File Created: 2002:02:13:15:29:58
Last Updated: 2002:02:13:15:29:58