Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1462
  • Last Modified:

File Access Denied Error

I used a routine I found here for doing a quick file search.  I had to alter it a little to accommodate partial strings.  It runs fine until about 100 searches through and then, on the first BlockRead, I receive an exception of "File Access Denied".  The file is opened in FormShow and closed in FormClose and has a filemode of Read Only.  Only this routine accesses it.  I'm sure I'm doing something really dumb but I just can't figure out what.

Any help????  Please!!!

Alexia

// file consists of a series of strings, each 24 characters long - padded if necessary, in the following format:
// #1234567^1234567^12^1234
// padchar is "?"
// need to retrieve the 24 character string if found
// need to make sure when searching for #123 that #123^ is found rather than #1234567^ etc.
const
  BufferSize = $8001;
var
  pBuf,pEnd,pScan,pPos: pChar;
  Filesize: LongInt;
  BytesRemaining: LongInt;
  BytesToRead: Integer;
  SearchFor: pChar;
  FindLen: LongInt;
  S: Array [0..23] of Char;
  NDB,FoundStr: String;
  StrIdx: Word;
  PartialMatch: Boolean;
begin
  FindLen := 24;

  Result := '';  //assume failure
  if (Length(forString)=0) then Exit;
  SearchFor := NIL;
  pBuf := NIL;

  System.Reset(ConvertFile,1);
  try
    //allocate memory for buffer
    GetMem(pBuf,BufferSize);
    Filesize := System.Filesize(ConvertFile);

    //allocate memory for pchar search string
    SearchFor := StrAlloc(Length(forString)+1);
    StrPCopy(SearchFor,forString);

    BytesRemaining := Filesize;
    pPos := NIL;
    PartialMatch := FALSE;
    While BytesRemaining>0 do begin
      //calc how many bytes to read this round
      if BytesRemaining>=BufferSize then BytesToRead := Pred(BufferSize)
        else BytesToRead := BytesRemaining;
      //read a buffer full and zero terminate the buffer
      try
        BlockRead(ConvertFile,pBuf^,BytesToRead,BytesToRead);
      except
        on e: EInOutError do begin
          MessageDlg(E.Message,mtError,[mbOK],0);  //here is where I get the File Access Denied
          Exit;
          end;
        end;
      pEnd := @pBuf[BytesToRead];
      pEnd^ := #0;
      //find string
      pScan := pBuf;
      While pScan<pEnd do begin
        pPos := StrPos(pScan,SearchFor);  //search for string
        if (pPos<>NIL) then begin   //possibly found it
          StrLCopy(S,pPos,FindLen);
          FoundStr := String(S);    // ex: #12345^01001a^36^345????
          StrIdx := 1;
          NDB := '';
          While FoundStr[StrIdx]<>'^' do begin  //NDB would be #12345
            NDB := NDB+FoundStr[StrIdx];
            Inc(StrIdx);
            end;
          if forString=NDB then begin
            Delete(FoundStr,1,1);  //12345^01001a^36^345????
            While FoundStr[Length(FoundStr)]=PadChar do Delete(FoundStr,Length(FoundStr),1); //12345^01001a^36^345
            Result := FoundStr;
            break;
            end
          else PartialMatch := TRUE;
          end;
        if PartialMatch then begin   //move past to next string if looking for #123, not #12345
          pScan := pPos+FindLen;
          PartialMatch := FALSE
          end
        else begin
          pScan := StrEnd(pScan);
          Inc(pScan);
          end;
        end;
      if pPos<>NIL then break;
      BytesRemaining := BytesRemaining-BytesToRead;
      if BytesRemaining>0 then begin
        Seek(ConvertFile,FilePos(ConvertFile)-Length(forString));
        BytesRemaining := BytesRemaining+Length(forString);
        end;
      end;
  finally
    if SearchFor<>NIL then StrDispose(SearchFor);
    if pBuf<>NIL then FreeMem(pBuf,BufferSize);
    end;
end;
0
alexiat
Asked:
alexiat
  • 2
1 Solution
 
BlackTigerXCommented:
try calling

CloseFile(ConvertFile)

on the finally part...

finally
  CloseFile(ConvertFile);
    if SearchFor<>NIL then StrDispose(SearchFor);
    if pBuf<>NIL then FreeMem(pBuf,BufferSize);
end;
0
 
alexiatAuthor Commented:
I believe System.Reset first closes and then reopens the file; however, I tried adding an additional CloseFile as you suggested and the same problem exists.
0
 
wavgetCommented:
Set the FileMode variable

From the Help File:

Indicates the access mode on typed and untyped files opened by the Reset procedure.

Unit

System

Category

I/O routines

var FileMode: Byte = 2;

Description

The FileMode variable determines the access mode to use when typed and untyped files (not text files) are opened using the Reset procedure.

The default FileMode is 2 (Read/Write access). Assigning another value to FileMode causes all subsequent Resets to use that mode. The SysUtils unit declares a number of file open mode constants that can be assigned to the FileMode variable.

Note:      Be sure to reset FileMode before calling Reset with a read-only file. Even if you are only reading from the file, the default FileMode value (Read/Write access) will cause an attempt to open a read-only file to fail.

Warning:      FileMode is declared as a variable, not as a threadvar. Therefore this variable is not thread-safe.

In other words, FileMode := fmOpenRead; before you open a read-only file will do the trick.

D2.
0
 
alexiatAuthor Commented:
Jeez, I knew it would be something simple.  I set the Filemode in FormShow but not in the subsequent Reset.  Your warning is important and something I didn't know.  Thanks.
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now