Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

AT() Function on Memo Field Causing "file read error".

Status
Not open for further replies.

Brak

Programmer
Jul 11, 2001
158
US
I am using the AT() function to search for the number to times a sequence of characters appears in a text stored in a memo field.
After the count reaches 140779 give produces a "file read error" error message.

If there is only 140778 then the AT() should just return a 0 instead of giving me an error message.

So what is the problem, and what can I do to solve it?

Thanks in advance.
 
Each version of Foxpro has its own limits and it sounds like you've found one.

Which version are you using?

Occurs() would be better for this purpose than AT(), but I don't remember which version introduced it.
 
OCCURS() is indeed a valid Function in FPW2.6.

I just checked my old FPW2.6 Help and found it.

If you have questions, look into your own help for how to use the OCCURS() Function

You may indeed encounter the same error message due to some other 'gotcha', but it is worth a try and it will more quickly/effectively give you a count of the number to times a sequence of characters appears in a text string.

Good Luck,
JRB-Bldr
 
Thank you so much for the info. Even though I have been programming in Fox for almost 18 year I never knew that function existed!

I ran the function but I got an "string to long to fit" error.
 
You might try doing a loop to acquire parts of the Memo field value using SUBSTR() which are small enough to not generate the error and add up the OCCURS() values as you go.

Good Luck,
JRB-Bldr
 
Yes, that would make sense. String limits were smaller in FP2.x than what we enjoy today in VFP. The string limit was 16K if I recall correctly (which may very well not be the case).

The only workaround is going to be breaking that text into smaller chunks.

Use COPY MEMO to write to a temp file, and then use LLFNs to read chunks smaller than 16K from the text file until you've worked all the way through.

(Even with all those steps it should still be quite quick.)
 
That's a good idea if I was searching for single characters. But I am searching for a string - so splitting the search up would not work as if the string I'm looking for is at the "seam" it wouldn't be counted.

I wonder why this function kicks out a "too long" error when the AT() didn't, but rather gave a "read file" if looking beyond 140778.
 
I'm afraid you're looking at either not getting it done at all or doing it the only way you can (which includes accounting for the string spanning the "seam"). The spanning problem can be solved easily by simply starting each chunk early enough to account for the length of the search string at the end of the previous chunk.

Nobody knows why the two functions give two different error messages, but most likely it's because one of them dates from dBase and the other came later and is plugged into better error reporting.

This isn't a new problem by any means. It's always solved by brute force programming.
 
If, by whatever means, you get the entire Memo field value into a number of strings, you can then do a OCCURS() on the composite string.

Code:
  * --- By whatever means populate the various cStringN --- 
  * --- variables with the overall Memo Field Value ---
  nTestStrCount = OCCURS(cTstString,(cString1 + cString2 + cString3)

I just tested the above with the following and it accurately shows the number of "0"'s:
Code:
cString1 = repl('1',999) + "0"
cString2 = repl('1',999) + "0"
cString3 = repl('1',999) + "0"
cString4 = repl('1',999) + "0"
cString5 = repl('1',999) + "0"
cString6 = repl('1',999) + "0"
cString7 = repl('1',999) + "0"
cString8 = repl('1',999) + "0"
cString9 = repl('1',999) + "0"
?OCCURS("0",(cString1 + cString2 + cString3 + cString4 + cString5 + cString6 + cString7 + cString8 + cString9))

Perhaps that approach would eliminate your issue of the Test String possibly occurring at the boundary.

Good Luck,
JRB-Bldr
 
String limits were smaller in FP2.x than what we enjoy today in VFP. The string limit was 16K if I recall correctly (which may very well not be the case).
Ah, the old days, I remember FPD 2.6 had a max limit of 1KB in a parameter. Oh well, that's not the subject at hand...

Today's VFP 9.0 appears to have a maximum memo field length of 16MB but I determined that by experimentation, I didn't find it in the VFP system capacities chart. I don't know what the maximum size is for your version, but the code below assumes it is similar.

Presuming your version can use SUBSTR() up to the maximum size of your memo fields, then this should work.
Code:
FUNCTION myOccurs
PARAMETERS cSearchExp, cSearchFld, nBlockSize
PRIVATE nMemoLen, nBlock, cChunk, nBeg, nEnd, nMatches
nMemoLen = LEN(EVALUATE(cSearchFld))
nBlock = IIF(TYPE("nBlockSize")="N", nBlockSize, 15000)  && optional, set 15000 as default block size
cChunk = ""
nBeg = 0
nMatches = 0
IF nBlock > LEN(cSearchExp)
   DO WHILE nBeg + LEN(cChunk) <= nMemoLen
      IF nBeg = 0
         nBeg = 1
      ELSE
         nBeg = nEnd - (LEN(cSearchExp)-1)
      ENDIF	
      nEnd = MIN(nBeg + nBlock - 1, nMemoLen)
      cChunk = SUBSTR(EVALUATE(cSearchFld), nBeg, nBlock - 1)
      nMatches = nMatches + OCCURS(cSearchExp, cChunk)
   ENDDO
ELSE
   ? "You specified a search block size smaller than the search expression."
ENDIF
RETURN nMatches
This is an example using myOccurs(). Remember to include the alias if you are not in that work area.
Code:
? myOccurs("text here", "MyMemoFld", 5000)
* if 3rd parm not sent, default is 15000
 
This code is incorrect.
Code:
IF nBlock > LEN(cSearchExp)
This code is better.
Code:
IF nBlock => LEN(cSearchExp)
 
This code addresses the possibility of the search phrase lying across the end boundary of the string segment being searched. To handle that possibility, the next segment (which I named nChunk) begins not on the next character after the end of the segment but offset backward for the length of the search phrase less 1.
 
Today's VFP 9.0 appears to have a maximum memo field length of 16MB but I determined that by experimentation, I didn't find it in the VFP system capacities chart. I don't know what the maximum size is for your version, but the code below assumes it is similar.

This is incorrect. Memo fields are limited only by disk space and the 2GB file size limit.

The 16MB limitation you've observed applies to strings in memory -- not to memo fields themselves.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top