Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsVB SyntaxEnterprise DevelopmentDatabase AccessControlsCOMWin APICrystal ReportDeploymentGeneralGeneral 2
Related Topics
VB.NET / ASP.NETMS SQL ServerMS AccessOther Database ProductsMore Topics ...

VB Forum / Win API / October 2003



Tip: Looking for answers? Try searching our database.

Flush File Data Buffers

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Michael D. Ober - 29 Oct 2003 20:55 GMT
How can I flush the file buffers from a file opened with the VB open
statement?  Direct API calls are ok.

open "foo.txt" for output as 1
print #1, "This is a line"

' The next line is what I need
flush #1

' more print statements
close #1

Thanks,
Mike.
Tom Esh - 29 Oct 2003 21:04 GMT
>How can I flush the file buffers from a file opened with the VB open
>statement?  Direct API calls are ok.
[quoted text clipped - 7 lines]
>' more print statements
>close #1

See the Reset method.

-Tom
MVP - Visual Basic
(please post replies to the newsgroup)
Michael D. Ober - 29 Oct 2003 21:27 GMT
Can it be done without closing the files?

Mike.

> >How can I flush the file buffers from a file opened with the VB open
> >statement?  Direct API calls are ok.
[quoted text clipped - 13 lines]
> MVP - Visual Basic
> (please post replies to the newsgroup)
Tom Esh - 29 Oct 2003 22:31 GMT
>Can it be done without closing the files?

Have a look at the FlushFileBuffers Api function. You would have to
first open the file with Api methods to get a handle (VB and Api file
handles are not interchangeable), but I don't see anything that says
it won't work if multiple handles are in use.

-Tom
MVP - Visual Basic
(please post replies to the newsgroup)
Tony Proctor - 30 Oct 2003 09:55 GMT
FlushFileBuffers will not flush any data held by the VB run-time's file
support. It is highly likely that this will hold buffers for record
blocking/de-blocking.

As Adam says, later, you need to use the WINAPI functions throughout,
possibly with a VB wrapper around them.

Depending on what the OP is trying to achieve, it's also worth looking at
the FILE_FLAG_WRITE_THROUGH flag to CreateFile(). This guarantees that each
individual WriteFile() operation is pushed "through" the file cache until it
safely reaches the disk. Hence, no need to worry about calling
FlushFileBuffers().

           Tony Proctor

> >Can it be done without closing the files?
>
[quoted text clipped - 6 lines]
> MVP - Visual Basic
> (please post replies to the newsgroup)
Tony Proctor - 30 Oct 2003 13:58 GMT
Sorry, I meant to refer to the reply from "Frank Adam", not "Adam"

       Tony

> FlushFileBuffers will not flush any data held by the VB run-time's file
> support. It is highly likely that this will hold buffers for record
[quoted text clipped - 21 lines]
> > MVP - Visual Basic
> > (please post replies to the newsgroup)
Frank Adam - 29 Oct 2003 23:08 GMT
>Can it be done without closing the files?

Yes... You do need FlushFileBuffers(), but that requires that you use
native win32 file i/o. VB doesn't give us a valid handle to our files,
which truely sucks, considering that it does use CreateFile to open
files, but thems are the damn rules. :(

If this is paramount for you, then you should consider writing a
wrapper for the CraeteFile, WriteFile and ReadFile APIs, and then you
can pass the handle returned by CreateFile to FlushFileBuffers.
Note that this is simply a memory flush,it does not flush the disk
cache itself to disk physical, but the H/D cache is pretty efficient.

ps: IIRC, the MSDN has a VB example on using WriteFile from VB, but
it's not rocket science if you can't find it.

Signature

Regards, Frank

J French - 30 Oct 2003 12:46 GMT
Frank has given you a pretty comprehensive answer

Another approach is to Close and then re-open the File
- I strongly recommend doing this if one is *extends* a file and is
not going to write to it again within say 1 second

It might be an idea to post what you are really trying to do, it looks
suspiciously as if you are trying to write to a log file that can be
read by another App

>How can I flush the file buffers from a file opened with the VB open
>statement?  Direct API calls are ok.
[quoted text clipped - 10 lines]
>Thanks,
>Mike.
Michael D. Ober - 30 Oct 2003 15:09 GMT
I am indeed attempting to write a log file.  VB gives you the option of
setting the record length to 1, but that generates an incredible amount of
overhead.  Being able to flush the file after each non-blank line is
critical so if a program crashes, I can start isolating the crash location
using log file entries.  By the way, the logfile is a class, so I have
encapsulated the inner workings.  Reading from another app during the
current apps processing isn't a requirement, but it would be nice.

Mike.

> Frank has given you a pretty comprehensive answer
>
[quoted text clipped - 20 lines]
> >Thanks,
> >Mike.
Tony Proctor - 30 Oct 2003 15:13 GMT
It sounds like the FILE_FLAG_WRITE_THROUGH is just what you need then
Michael

       Tony Proctor

> I am indeed attempting to write a log file.  VB gives you the option of
> setting the record length to 1, but that generates an incredible amount of
[quoted text clipped - 30 lines]
> > >Thanks,
> > >Mike.
Larry Serflaten - 30 Oct 2003 15:19 GMT
> I am indeed attempting to write a log file.  VB gives you the option of
> setting the record length to 1, but that generates an incredible amount of
[quoted text clipped - 3 lines]
> encapsulated the inner workings.  Reading from another app during the
> current apps processing isn't a requirement, but it would be nice.

Closing the file after each write would protect you from program crashes.

LFS
J French - 30 Oct 2003 15:26 GMT
>I am indeed attempting to write a log file.  VB gives you the option of
>setting the record length to 1, but that generates an incredible amount of
[quoted text clipped - 3 lines]
>encapsulated the inner workings.  Reading from another app during the
>current apps processing isn't a requirement, but it would be nice.

Right, gottit

You need to open the file for Append

Another method is to pre-format the file and open it in Binary mode,
keeping track of your 'logical' end of file.

The major problem is not so much flushing the file buffers, as
updating the Directory entry after a file has been extended.

I would look at the Open for Append - unless you are logging dozens of
lines per second
- in which case I would have another App doing the logging
- say an AX EXE
- or even something 'listening' on a Windows Hook

Actually I reckon that is the best idea by far
Don@home.com - 30 Oct 2003 16:07 GMT
>I am indeed attempting to write a log file.  VB gives you the option of
>setting the record length to 1, but that generates an incredible amount of
[quoted text clipped - 5 lines]
>
>Mike.

Is this NOT the Case....

Open File....
Print #....
Close #....
At this point the file no longer belongs to you but it belongs to Windows <?¿?>

Here is an example to play with (if you are interested)
I have tried others but the results are the same... The Temp.Txt file always has
a list from 0 to 4...

Can someone Not make it work..

Option Explicit

Private lLp As Long

Private Sub FileHandler()
Dim lFF As Long
   lFF = FreeFile
   If lLp > 0 Then
       Open "d:\temp\temp.txt" For Append As #lFF
       Print #lFF, CStr(lLp)
       Close #lFF
   Else
       Open "d:\temp\temp.txt" For Output As #lFF
       Close #lFF
       Open "d:\temp\temp.txt" For Append As #lFF
       Print #lFF, CStr(lLp)
       Close #lFF
   End If
End Sub

Private Sub Form_Click()
   For lLp = 0 To 10
       If lLp = 5 Then
           lLp = 1 / 0 'Cause it to Crash...
       Else
           FileHandler
       End If
   Next lLp
End Sub

Have a good day...

Don
Michael D. Ober - 30 Oct 2003 16:48 GMT
First, thanks to all who replied.  The CreateFile API was the kicker.  I
have successfully used in C and C++, but had been unsuccessful in VB.  I
chose not to use the FILE_FLAG_WRITE_THROUGH flag on the open because there
is no need to flush empty lines.  In my original request for assistance, I
said that API calls were ok.  As you can see, I was already using the
GetLocalTime API call, and as a C programmer, I'm comfortable with them.  My
previous attemts to use CreateFile failed because I didn't have the function
prototype correct.  I have left the VB open/write/close statement in for
comparison.

Thanks,
Mike Ober.

'============================ logfile.cls
Option Explicit
Option Compare Text

'Source: i:\mis_stuff\vbcollections\library\logfile.cls
'Documentation: i:\mis_stuff\vbcollections\library\Library
Specifications.doc#Objects\LogFile"
'8 Jun 01  mdo Initial documentation
'30 Oct 03 mdo Converted to use Win32 API
CreateFile/WriteFile/FlushFileBuffers/CloseHandle with
'                       the assistance of several "Netizins"
'                       Now each non-blank line is flushed when it is
written.  Blank lines are buffered.

Private BaseFile As String
Private FileName As String
Private FileNum As Long
Private Opened As Date
Public UseVersion As Boolean

Private Type SYSTEMTIME
 wYear As Integer
 wMonth As Integer
 wDayOfWeek As Integer
 wDay As Integer
 wHour As Integer
 wMinute As Integer
 wSecond As Integer
 wMilliseconds As Integer
End Type
Private Declare Sub GetLocalTime Lib "kernel32" (lpSystemTime As SYSTEMTIME)

Private Const FILE_SHARE_READ = &H1
Private Const FILE_SHARE_WRITE = &H2
Private Const OPEN_ALWAYS = 4
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const INVALID_HANDLE_VALUE = -1

Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA"
(ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal
dwShareMode As Long, ByVal lpSecurityAttributes As Any, ByVal
dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal
hTemplateFile As Long) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long,
lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten
As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function FlushFileBuffers Lib "kernel32" (ByVal hFile As
Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long)
As Long

Public Sub WriteLog(Optional ByVal Message As String = "")
 Dim tm As SYSTEMTIME
 Dim written As Long

 On Error GoTo Reopen
 If FileNum <> INVALID_HANDLE_VALUE Then
   'If FileNum <> 0 Then
   Reopen
   If Message <> "" Then
     GetLocalTime tm
     Message = Format(tm.wYear, "0000") & Format(tm.wMonth, "00") &
Format(tm.wDay, "00") & " " & _
         Format(tm.wHour, "00") & "." & Format(tm.wMinute, "00") & "." &
Format(tm.wSecond, "00") & "." & Format(tm.wMilliseconds, "000") & _
         vbTab & Message
   End If
retry:
   Message = Message & vbNewLine
   WriteFile FileNum, ByVal Message, Len(Message), written, vbNullString
   If Message <> vbNewLine Then FlushFileBuffers FileNum
   'Print #FileNum, Message
 End If
 Exit Sub

Reopen:
 FileNum = CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_READ Or
FILE_SHARE_WRITE, ByVal 0&, OPEN_ALWAYS, 0, 0)
 'Open FileName For Append As FileNum
 Resume retry
End Sub

Private Sub Class_Initialize()
 FileNum = INVALID_HANDLE_VALUE
 'FileNum = 0
 FileName = ""
 UseVersion = True
End Sub

Private Sub Class_Terminate()
 WriteLog "Log File closing by object going out of Scope"
 'If FileNum <> 0 Then Close #FileNum
 If FileNum <> INVALID_HANDLE_VALUE Then CloseHandle FileNum
End Sub

Public Property Get Name() As String
 Name = FileName
End Property
Public Property Let Name(FileBase As String)
 Dim os As New OSInterface

 ' If no name is given, close existing log file and exit
 If FileBase = "" Then
   'If FileNum <> 0 Then
   If FileNum <> INVALID_HANDLE_VALUE Then
     WriteLog "Log file closing; no new logfile being opened"
     CloseHandle FileNum
     FileNum = INVALID_HANDLE_VALUE
     'Close #FileNum
     'FileNum = 0
   End If
   Exit Property
 End If

 ' Generate logfile name from FileBase
 Opened = Date
 If InStr(FileBase, "\") = 0 Then
   BaseFile = Environ$("LOGDIR")
   If BaseFile = "" Then BaseFile = "c:"
   BaseFile = TrailSlash(BaseFile)
 Else
   BaseFile = Left$(FileBase, InStrRev(FileBase, "\") - 1)
   FileBase = Mid$(FileBase, InStrRev(FileBase, "\") + 1)
 End If

 ' Ensure directory exists for new logfile
 os.CreateDirectory BaseFile

 If UseVersion Then
   If InStr(FileBase, " v.") = 0 Then FileBase = FileBase & " v." &
App.Major & "." & App.Minor & "." & App.Revision
 End If

 BaseFile = TrailSlash(BaseFile) + FileBase + " - " + UCase(os.UserName) +
" on " + UCase(os.ComputerName) + " - "
 FileName = BaseFile + Format$(Opened, "YYYYMMDD") + ".LOG"

 ' Can only write to one log file at a time
 If FileNum <> INVALID_HANDLE_VALUE Then
 'If FileNum <> 0 Then
   WriteLog "Log file closing; new logfile '" & FileName & "' being opened"
   CloseHandle FileNum
   'Close #FileNum
 End If

 ' Now open new logfile
 'FileNum = FreeFile(1)
 'Open FileName For Append As #FileNum
 FileNum = CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_READ Or
FILE_SHARE_WRITE, ByVal 0&, OPEN_ALWAYS, 0, 0)
 WriteLog "Log File " + FileName + " opened"
End Property

Public Sub Reopen(Optional force As Boolean = False)
 If Date <> Opened Then
   Opened = Date
   WriteLog "Day Change Closure"
   'Close #FileNum
   'FileNum = FreeFile(1)
   'Open FileName For Output As #FileNum
   CloseHandle FileNum
   FileName = BaseFile + Format$(Opened, "YYYYMMDD") + ".LOG"
   FileNum = CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_READ Or
FILE_SHARE_WRITE, ByVal 0&, OPEN_ALWAYS, 0, 0)
   WriteLog "Log File " + FileName + " opened by date change"
 ElseIf force Then
   WriteLog "Forced Reopen of Logfile"
   'Close #FileNum
   'FileNum = FreeFile(1)
   'Open FileName For Output As #FileNum
   CloseHandle FileNum
   FileNum = CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_READ Or
FILE_SHARE_WRITE, ByVal 0&, OPEN_ALWAYS, 0, 0)
   WriteLog "Reopen complete"
 End If
End Sub
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.