Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Function horribly slow

0 views
Skip to first unread message

Patrick Weidener

unread,
Oct 7, 2008, 6:31:08 PM10/7/08
to
Can anyone tell me why this function is so horribly slow (on some PCs)???

Public Function FileForceCopy(ByVal uSource As String, ByVal
uDestination As String) As Boolean
On Error GoTo ErrHandler

Dim lSourceLen&
Dim iSF%
Dim iDF%
Dim sChunk As String
Dim iBytesToGet%
Dim lBytesCopied&

Debug.Print uSource
Debug.Assert FileExists(uSource)

'/* Get source file length */
lSourceLen = FileLen(uSource)

'/* Open both files */
iSF = FreeFile()

'/* We MUST open a file after calling FreeFile(), else the next
FreeFile will be the same number */
Open uSource For Binary Shared As #iSF

'/* Only know we can call the next FreeFile() */
iDF = FreeFile()

Debug.Print uDestination
TryKill uDestination

If FileExists(uDestination) Then
Debug.Print "Source: " & uSource
Debug.Print "Destination: " & uDestination
Debug.Assert False
Exit Function
End If

Debug.Print uDestination

Open uDestination For Binary As #iDF

'How many bytes to get each time
iBytesToGet = 4096 '4kb
lBytesCopied = 0

'Keep copying until finishing all bytes
Do While lBytesCopied < lSourceLen
'Check how many bytes left
If iBytesToGet < (lSourceLen - lBytesCopied) Then
'Copy 4 KBytes
sChunk = Space(iBytesToGet)
Get #iSF, , sChunk
Else
'Copy the rest
sChunk = Space(lSourceLen - lBytesCopied)
Get #iSF, , sChunk
End If
lBytesCopied = lBytesCopied + Len(sChunk)

'Put data in destination file
Put #iDF, , sChunk
Loop

Close #iSF
Close #iDF

FileForceCopy = True

Exit Function
ErrHandler:
Debug.Print Err.Description
Debug.Assert FileExists(uSource)
'Debug.Print Len(uSource)
Debug.Print uDestination
Debug.Print uSource
Debug.Assert False
Call WriteLog("#FileForceCopy: " & Err.Description & ", err.number: " &
Err.Number & ", Params: '" & "" & "'")
End Function

Patrick Weidener

unread,
Oct 7, 2008, 6:42:02 PM10/7/08
to
I was using this function on an USB-stick. I tried to copy a file from
the hard disk to the USB-stick.
After 20 minutes I went to the other computer to see if it was done now.
It wasn't. I then discovered that the Autoplay window opened for the
USB-Stick (where Windows asks what I want do). I closed this window, and
my function was suddenly done/ completed. Did somebody experience a
similar behaviour before?

Karl E. Peterson

unread,
Oct 7, 2008, 9:23:49 PM10/7/08
to
Patrick Weidener wrote:
> Can anyone tell me why this function is so horribly slow (on some PCs)???

The buffer's awfully small by today's standards. I'd use 4Mb rather than 4Kb, for
example. No need to recreate it on each loop, either.

Also, you're gonna get *clobbered* on performance by, and risking data corruption
due to, UniMess -- you're doing binary file i/o with Strings! Nasty. Use Byte
arrays instead.
--
.NET: It's About Trust!
http://vfred.mvps.org

Patrick Weidener

unread,
Oct 8, 2008, 2:33:29 AM10/8/08
to
Karl, thanks.
Can't you quickly do it?

Patrick Weidener

unread,
Oct 8, 2008, 5:32:02 AM10/8/08
to
I mean I don't see where I am using a string instead of bytes.

Larry Serflaten

unread,
Oct 8, 2008, 8:20:52 AM10/8/08
to

"Patrick Weidener" <pawei_...@gmx.net> wrote

> I mean I don't see where I am using a string instead of bytes.

This may be a clue...

> Dim sChunk As String


Another example of copying a file:
http://groups.google.com/group/microsoft.public.vb.general.discussion/msg/fd9ebdf0ed1c5750?hl=en

HTH
LFS


Mike Williams

unread,
Oct 8, 2008, 8:25:03 AM10/8/08
to
"Patrick Weidener" <pawei_...@gmx.net> wrote in message
news:uC6v$iSKJH...@TK2MSFTNGP06.phx.gbl...

> I mean I don't see where I am using a string instead of bytes.

You're declaring the variable sChunk as a String and assigning a string of
4096 space characters to it using the following code:

Dim sChunk As String
Dim iBytesToGet%

iBytesToGet = 4096 '4kb
sChunk = Space(iBytesToGet)

So each time you use the line . . .

Get #iSF, , sChunk

. . . you are loading 4096 bytes of the file into a String (into the sChunk
string). This requires VB to load 4096 bytes of data from the file buffer
and convert them to a standard VB "two bytes per character" string which
will have a character length 4096 and a byte length 8192, which will slow
things down. The reverse is the case when you use Put to output the string
to the new file, slowing things down once more. Also you are repeatedly
assigning a 4096 character string at every iteration of the For Next loop
instead of just once at the beginning, which is unnecessary and which will
slow things down even further. I'm not sure how much the slowdown will
affect the overall speed of your code, given that disk I/O is not usually
the fastest thing on the planet itself, but you should be able to perform
some tests yourself to check that, preferably using a large number of
individual files rather than the same file in a loop for testing. In any
case, you would be well advised to use a Byte array instead of a String, as
pointed out by Karl.

Mike


Norm Cook

unread,
Oct 8, 2008, 8:28:24 AM10/8/08
to
"Patrick Weidener" <pawei_...@gmx.net> wrote in message
news:uC6v$iSKJH...@TK2MSFTNGP06.phx.gbl...
>I mean I don't see where I am using a string instead of bytes.

He means that your data transfer buffer, sChunk, is a string.

You can easily convert your routine by changing
sChunk As String
to
bChunk As Byte()

Then instead of sChunk = Space$(), use
ReDim bChunk(iBytesToGet - 1), or if you prefer
ReDim bChunk(1 To iBytesToGet)

Then just use
Get #iSf , , bChunk
Put #iDf , , bChunk

Jason Keats

unread,
Oct 8, 2008, 8:30:26 AM10/8/08
to
Patrick Weidener wrote:
> I mean I don't see where I am using a string instead of bytes.

You Get and Put sChunk, where sChunk is a string.

I believe Karl is suggesting the use of a byte array.

For example, here's a function to read a file into a byte array...

Public Function GetBinaryFileContents(ByVal sFilename As String) As Byte()

Dim nF As Integer
Dim lFileLen As Long
Dim ayBytes() As Byte

lFileLen = FileLen(sFilename)

nF = FreeFile
ReDim ayBytes(0 To lFileLen - 1)

Open sFilename For Binary As #nF
Get #nF, 1, ayBytes
Close #nF

GetBinaryFileContents = ayBytes

End Function

HTH

Patrick Weidener

unread,
Oct 8, 2008, 8:39:57 AM10/8/08
to
Thank you!
Could you please all look at my code again? I am so horrified that it
might fail under some conditions. Also I don't know if I didn't make any
mistake when I included your tipps.

Public Function FileForceCopy(ByVal uSource As String, ByVal
uDestination As String) As Boolean
On Error GoTo ErrHandler

Dim lSourceLen&
Dim iSF%
Dim iDF%

Dim bChunk() As Byte
Dim lBytesToGet&
Dim lBytesCopied&

Debug.Print uSource
Debug.Assert FileExists(uSource)

'/* Get source file length */
lSourceLen = FileLen(uSource)

'/* Open both files */
iSF = FreeFile()

'/* We MUST open a file after calling FreeFile(), else the next
FreeFile will be the same number */
Open uSource For Binary Shared As #iSF

'/* Only know we can call the next FreeFile() */
iDF = FreeFile()

Debug.Print uDestination
TryKill uDestination

If FileExists(uDestination) Then
Debug.Print "Source: " & uSource
Debug.Print "Destination: " & uDestination
Debug.Assert False
Exit Function
End If

Debug.Print uDestination

Open uDestination For Binary As #iDF

'How many bytes to get each time

lBytesToGet = 4096000 '/* Is that correct??? */
lBytesCopied = 0

'/* Keep copying until finishing all bytes */
Do While lBytesCopied < lSourceLen
'/* Check how many bytes left */
If lBytesToGet < (lSourceLen - lBytesCopied) Then
'/* Copy 4000 KBytes */
ReDim bChunk(1 To lBytesToGet)
Get #iSF, , bChunk
Else
'/* Copy the rest */
bChunk = Space(lSourceLen - lBytesCopied)
Get #iSF, , bChunk
End If
lBytesCopied = lBytesCopied + UBound(bChunk)

'/* Put data in destination file */
Put #iDF, , bChunk

Wolfgang Enzinger

unread,
Oct 8, 2008, 8:21:05 AM10/8/08
to
On Wed, 08 Oct 2008 11:32:02 +0200, Patrick Weidener wrote:

>I mean I don't see where I am using a string instead of bytes.

Dim sChunk As String

Replace that sChunk string by a byte array.

Wolfgang

Jason Keats

unread,
Oct 8, 2008, 9:00:54 AM10/8/08
to


You need to change the line:

bChunk = Space(lSourceLen - lBytesCopied)

Use ReDim.

There's probably other problems - but I'm too scared to run the code on
my machine! ;-)

Patrick Weidener

unread,
Oct 8, 2008, 9:18:13 AM10/8/08
to
Everybody is just making suggestions and saying "Make it bytes", but
nobody is posting complete code, even not Norman who did a lot but still
left some uncertainties. Are you are scared as me?

dpb

unread,
Oct 8, 2008, 9:26:20 AM10/8/08
to

No, the question was answered; go learn and if have specific
questions/problems _then_ ask about them...

It gets to be a point where it's like the folks who come asking in
desperation for solutions to homework problems the last minute--folks
here are extremely helpful _up_to_a_point_.

--

Jason Keats

unread,
Oct 8, 2008, 9:58:58 AM10/8/08
to
Jason Keats wrote:
> You need to change the line:
>
> bChunk = Space(lSourceLen - lBytesCopied)
>
> Use ReDim.

In case you haven't figured it out, change the above line in your
program to:

ReDim bChunk(1 To lSourceLen - lBytesCopied)

and all should be well.

Of course, your program will be unresponsive while it's copying large
files, and doesn't display a progress bar - but that's a separate problem.

HTH

Patrick Weidener

unread,
Oct 8, 2008, 10:10:15 AM10/8/08
to
No, the point is you cannot answer the question. I always help people if
I can and if they ask in a nice way (which I think I did). If people
then only reply by giving half wisdom away piece by piece they have to
much time on their hands plus they are better off in the sadomaso scene.

Jason Keats

unread,
Oct 8, 2008, 10:32:51 AM10/8/08
to

I'm not sure who you're addressing with this rant, however I'll respond.

What is your problem?

You received assistance.
You learned something.
You now have code that works.

Are you expecting others to write your code for you? Is our time less
valuable than yours?

dpb

unread,
Oct 8, 2008, 10:38:44 AM10/8/08
to


Plonk...

--

Dave O.

unread,
Oct 8, 2008, 10:40:46 AM10/8/08
to
"Patrick Weidener" <pawei_...@gmx.net> wrote in message
news:ejf4d%23UKJH...@TK2MSFTNGP03.phx.gbl...

No, you are missing the point, if you are given a full solution with
everything done for you, what will you learn?
However if you are told where your mistake is and what YOU need to do to fix
it then once you have done a bit of research using what you have been told
then you are far more likely to learn something useful.
Remember, you learn from your mistakes, if you get a fully functioning
solution you don't get much of a learning opportunity.
BTW "sadomaso" is an old term, "sub-dom" is the currently preferred term, or
so I'm told.

Dave O.


Patrick Weidener

unread,
Oct 8, 2008, 3:18:53 PM10/8/08
to
I was only referring to dpd.
Thanks for the help!

MikeD

unread,
Oct 8, 2008, 5:55:54 PM10/8/08
to

"Patrick Weidener" <pawei_...@gmx.net> wrote in message
news:eUydYhUK...@TK2MSFTNGP03.phx.gbl...

> Everybody is just making suggestions and saying "Make it bytes", but
> nobody is posting complete code, even not Norman who did a lot but still
> left some uncertainties. Are you are scared as me?

We're not here to write your code for you. That's YOUR job. If you can't
understand or accept that, then you're not going to get much help here of
ANY kind.

--
Mike


Karl E. Peterson

unread,
Oct 8, 2008, 8:53:22 PM10/8/08
to
Patrick Weidener wrote:
> Could you please all look at my code again? I am so horrified that it
> might fail under some conditions.

Nothing(!) is more fraught with potential error situations than file i/o. Yes, your
code may very well (cancel that, *will*) fail in numerous situations. For example,
what happens if the destination device is read-only, fills-up, doesn't exist, gets
ejected, etc?

You either need to approach this task with a *real* spirit of adventure, seeking to
grow and learn, or ask yourself why you're doing something manually that's built
into both the operating system and the language -- something that's, indeed, one of
the primary reasons operating systems were built in the first place?

Kevin Provance

unread,
Oct 8, 2008, 8:53:32 PM10/8/08
to
If you want a complete working code solution, it's 75 bucks an hour, 125 if
it involes API.

;-)

"Patrick Weidener" <pawei_...@gmx.net> wrote in message

news:ejf4d%23UKJH...@TK2MSFTNGP03.phx.gbl...

Patrick Weidener

unread,
Oct 10, 2008, 9:18:00 PM10/10/08
to
Yeah, like your house is worth 100.000 bucks :-)
www.lehman-brothers.com :-)

Patrick Weidener

unread,
Oct 10, 2008, 9:37:38 PM10/10/08
to
If I really wanted to pay somebody for coding I'd hire an Indian for 10
$ per hour.

Robert Morley

unread,
Oct 10, 2008, 11:03:10 PM10/10/08
to
Dave O. wrote:
> BTW "sadomaso" is an old term, "sub-dom" is the currently preferred term, or
> so I'm told.

It depends who you ask. Sadomasochism, SM, BDSM, etc., they're all good.
The words "Dom/sub", often written with "Dom" capitalized and "sub" not,
typically refer to the people involved. (Dom = dominant, sub = submissive,
in case anybody couldn't figure it out.)

And in case anyone feels the need to insert innuendo somewhere, I'll come
right out and say it: No, I didn't need to be told...I know first-hand. <LOL>

Rob

Kevin Provance

unread,
Oct 10, 2008, 11:10:01 PM10/10/08
to
Outsourcing. Good for you. Repuglican?

"Patrick Weidener" <pawei_...@gmx.net> wrote in message

news:uHPU6H0K...@TK2MSFTNGP02.phx.gbl...

0 new messages