Solved

can't open in use file even for reading

Posted on 2006-11-29
26
914 Views
Last Modified: 2010-04-05
I'm using the following function to mimic the tail command in unix.   It needs to open a file and read from it.  As you can see I'm only opening it in readonly mode but I still get the error that I cannot access the file.   Can anyone suggest an alternate method to accomplish this task?  

function tform1.Tail(FileName:string; Position:Integer):string;
var
  S: TStream;
  C: Char;
  L: Integer;
begin
  S := TFileStream.Create(FileName, fmOpenRead ,fmShareDenyNone);
  try
    S.Seek(Position, soBeginning);
    L := S.Size-Position;
    SetLength(Result, L);
    S.Read(Result[1], L);
  finally
    S.Free;
  end;
end;


Thanks!
0
Comment
Question by:hibbidiji
  • 13
  • 13
26 Comments
 
LVL 27

Accepted Solution

by:
kretzschmar earned 250 total points
ID: 18038651
it could be that another process did open this file exclusive
-> no chance to read it by your process
0
 
LVL 1

Author Comment

by:hibbidiji
ID: 18038778
Hiya Michael!
How about workarounds?   Executing a file copy then reading that temp file?   Anything else you can think of?
Thanks!
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 18038852
>Executing a file copy then reading that temp file?  
if you can copy it, then you should it also read it.

do a test, then we look further

btw. a similar q was here one/two years ago,
i will search it, maybe this solution is useable for u

meikl ;-)
0
 
LVL 1

Author Comment

by:hibbidiji
ID: 18038902
When using a shell copy function I can indeed copy the file, though my own internal functions seem to be keeping ahold of the file  - I'm sure I can chase that down though.  Here is my copy file function using shellapi
function scShellCopyFile(FormHandle : THandle; StrFrom, StrTo : string; BlnSilent : Boolean = False) : Boolean;
var
  F : TShFileOpStruct;
begin
  F.Wnd:=FormHandle;
  F.wFunc:=FO_COPY;
  F.pFrom:=PChar(StrFrom+#0);
  F.pTo:=PChar(StrTo+#0);
  F.fFlags := FOF_ALLOWUNDO or FOF_RENAMEONCOLLISION;
  if BlnSilent then
    F.fFlags := F.fFlags or FOF_SILENT;
  if ShFileOperation(F) <> 0 then
    result:=False
  else
    result:=True;
end;

0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 18038905
hmm, the other solution is exactly what you posted,
guess you got it from here :-))


can you copy the file?

meikl ;-)
0
 
LVL 1

Author Comment

by:hibbidiji
ID: 18038936
I found that I had an open filemap handle on the file and killed it - this let go of my file so I could mess about with the temp file.   I suppose the only question would be should the shell be able to copy a file yet delphi not be able to read it (readonly).  I have my solution to a point - it will work though it's a little roundabout.   Any other ideas do you think?
0
 
LVL 1

Author Comment

by:hibbidiji
ID: 18038942
Sorry for the cross post-  looks like this is the solution.   Thanks for pointing me at the untouchable file and have a great day.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 18038945
ok, didn't see your last comment before my last post

so it should be possible to read from the file

this kind of streamcreation i never used (seems to be a overloaded method)
  S := TFileStream.Create(FileName, fmOpenRead ,fmShareDenyNone);

maybe it makes a differentce if u use
  S := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);

a copy and then a read makes not much sense, if the file is huge,
but of course on smaller files it may be a workaround

meikl ;-)
0
 
LVL 1

Author Comment

by:hibbidiji
ID: 18038958
trying your solution now - will request a change if we get it fixed with your method
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 18038967
hups,

we are both really active at same time.
well, it is solved for you,
then i could paq this q and refund your points
with my role as Page Editor

meikl ;-)
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 18038974
puh, seems i am too slow :-))
0
 
LVL 1

Author Comment

by:hibbidiji
ID: 18038998
I'll see how my read goes with your code - this might be really helpful if it does help and I'm not worried on the points :)  I'll let you know what I come up with.  it's definitely different with the OR.  it appears to be freezing now - though that could just be the file scan.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 18039013
let me know, if i should reopen this question

if u use a memory maped file, then there may more possibilities,
but then i need more information and time to try

meikl ;-)
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 27

Expert Comment

by:kretzschmar
ID: 18039025
ok, keep me informed

(just again: see your last comment not, before posting)

meikl ;-)
0
 
LVL 1

Author Comment

by:hibbidiji
ID: 18039138
Alright,
When using your OR operator for that open action, I do not get the error that the file is in use at all.   My biggest problem seems to be in this function now.  It is supposed to open the file and count the number of characters in it. The files I'm dealing with are fairly small - under 10mb in general - and when run on an unlocked file it takes less than 2 seconds.  

When running this function on my locked file, it returns -1 instead of the correct number of characters.

Any idea why? I believe it's related to the question's original issue

note that in the following function I've also tried the flag FILE_FLAG_RANDOM_ACCESS in the createfile.


function GetFileLengthInCharacters(filename:string):integer;
var
filesize:integer;
FileHandle:tHandle;
CharCounter:integer;
begin


 FileHandle := CreateFile(pansichar(FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
 CharCounter := GetFileSize(FileHandle, nil);
 fileclose(filehandle);
 result := charcounter;

end;
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 18039314
?? would not be the charcount the filsize -1
(the filesize could be retrieved with the findfirst-api without open the file)

explain a bit more

meikl ;-)
0
 
LVL 1

Author Comment

by:hibbidiji
ID: 18039411
Perhaps I'm amiss here in that I misunderstood something that another programmer did because of his var names.   As I look now it does look like this is a roundabout way of doing it.   How would you rewrite the function to return the filesize?  What do you think the best way would be.

Remember that the output of this function should return a value that would be appropriate to the input of the tail function in my first post.  

thank you.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 18039606
maybe this way (not tested, just from head)

function getsize(APathFileName : String) : Integer;
var SRec : TSearchrec;
begin
  result := 0;
  try
    if findfirst(APathFileName, faAnyFile, SRec) > 0 then
      result := srec.Size;
  finally
    findclose(srec);
  end;
end;

meikl ;-)
0
 
LVL 1

Author Comment

by:hibbidiji
ID: 18039787
Yikes,
No luck.  Here's the status.

if I copy off a backup of the file, get the length, then use that for the input in the tail function, it DOES return data properly. This implies that the filestream that tail uses is good and it IS reading the file properly using that method.

The first method I used returns properly on the backup (unlocked) file and -1 on the locked file.

The findfirst method you pasted returns 0.  I modified it to return the actual return value (checking for a -1 or other errorcode but it's actually returning 0.  This would imply that it's not finding the file, I would assume.  However, i've been using the same var and value for the file as in the tail function so I can assume that it is indeed valid.   A caveat here is that the file I'm working with is on a UNC path i.e. \\domain\server\folder\file.txt

I did not find anything that states that UNC paths are not valid when using findfirst.

Any more ideas?  I CAN go back to copying to a temp file but it's obviously not the ideal solution.

0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 18040035
too late for me today to look deeper into your problem,
do you have a chance to change the "writer-process"?

until tomorrow (from my point)

meikl ;-)
0
 
LVL 1

Author Comment

by:hibbidiji
ID: 18054960
Back.
Sorry for the delay!
I never did get it to read from the file.  This is odd for a couple reasons:

windows can copy it without unlocking it
text editors can read from it without unlocking it

findfirst is still returning 0 (file not found) though the same var, which contains the path to the filename, can be used to copy the file with no issues.  the path is correct but findfirst just isn't working.

I'm about ready to give up and go with the file backup / read / etc method.  It's just frustrating because I know the file CAN be read - text editors are doing it.  I would just like to know why delphi isnt.

Ho hum
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 18055135
well, then it should possible with delphi also

did you simple tried to read it into a richedit?
just with
richedit1.lines.loadfromfile(FileName);
?

of course just as test, not as solution

meikl ;-)
0
 
LVL 1

Author Comment

by:hibbidiji
ID: 18057034
No dice.
I still get the following error when trying the loadfromfile

First chance exception at $7C812A5B. Exception class EFOpenError with message 'Cannot open file "\\server\file.txt". The process cannot access the file because it is being used by another process'. Process Project1.exe (2312)

I will repeat for clarity that I can, every time, open the file in notepad, notepad++, word and copy it through explorer

This is perplexing isn't it?
0
 
LVL 1

Author Comment

by:hibbidiji
ID: 18057070
to save possible time and confusion it should be noted that I replaced my actual filename and path with the \\server\file.txt
0
 
LVL 1

Author Comment

by:hibbidiji
ID: 18057243
Last (for today at least)
I wrote up a function in C++ that I would use to read the filesize but it ALSO returns -1:

void __fastcall TForm1::Button1Click(TObject *Sender)
{

   FILE *fp;
   int letter;

   if((fp = fopen("\\server\file.txt", "r")) == NULL)
   {
DWORD dwSizeLo, dwSizeHi;
dwSizeLo = GetFileSize ( fp, &dwSizeHi);
char buffer[35];
String mysize = ltoa(dwSizeLo, buffer, 10);
lbl->Caption = mysize;
   }

   fclose(fp);

}



No luck with this either.  This is really perplexing!
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 18058936
>This is really perplexing!
thats true

i will try to setup a similar case

meikl ;-)
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Suggested Solutions

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

708 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

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now