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
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
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
> 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
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
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
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
>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
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! ;-)
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_.
--
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
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?
Plonk...
--
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.
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
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?
;-)
"Patrick Weidener" <pawei_...@gmx.net> wrote in message
news:ejf4d%23UKJH...@TK2MSFTNGP03.phx.gbl...
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
"Patrick Weidener" <pawei_...@gmx.net> wrote in message
news:uHPU6H0K...@TK2MSFTNGP02.phx.gbl...