|
-
Dec 31st, 2009, 08:06 AM
#1
Thread Starter
Member
Last edited by astralist; Jan 10th, 2010 at 07:38 AM.
-
Dec 31st, 2009, 10:36 AM
#2
Re: [HELP] Unicode problem: read binary file at spesific position with unicode path
Can you help an idiot here by explaining what you mean by unicode path? Is lpFileName not unicode anyway?
-
Dec 31st, 2009, 03:55 PM
#3
Re: [HELP] Unicode problem: read binary file at spesific position with unicode path
This probably refers to either files where the path is longer than MAXPATH (around 260) and/or where the full path name contains characters that can't be mapped from a VB6 (Unicode) String to the ANSI codepage for the current locale.
Almost everything VB6 does with its native I/O statements involves such translation to ANSI so that VB6 programs can still work on Win9X machines where Unicode was not natively supported.
To work with files using Unicode paths you usually have to resort to the wide-char ("Unicode") versions of system API calls with names ending in W instead of A. You would then generally have to prefix pathnames with "\\?\" as well, which tells the system you are supplying a Unicode path.
VB6's Open statement will accept names starting with "\\?\" but I don't think this means that unmappable characters or paths exceeding MAXPATH will actually work. Lots of other VB6 I/O functions (such as Dir$() and GetAttr()) may fail if you feed them a "\\?\" path too.
A long-winded way of saying I think the OP wants to use paths containing some characters that don't map to his default ANSI codepage. I could be wrong about this, and I suppose it is also possible that characters which do successfully map but exceed &H7F after mapping fail too (accented letters, etc.).
-
Dec 31st, 2009, 06:44 PM
#4
Re: [HELP] Unicode problem: read binary file at spesific position with unicode path
CreateFileW, ReadFile & WriteFile APIs are unicode compatible. They have no problems with unicode path or file names. Once you have a file handle (CreateFileW), you can read the bytes into your array. Here's an example I use quite often, tweak to taste.
Note: I added the bUnicode variable in function below but never do that in my projects. I cache the value to a form-level variable in form load so the routines always know whether to use unicode or ansi APIs elsewhere in the project. Besides, caching it once is a bit faster vs testing every time.
Edited: For the GetFileHandle to work, the passed file name must be valid, it can't contain a path/filename like ?????. So if you are offering your customers an option to select a file, use a unicode version of the common dialog. A fair substitute example can be found in my signature below.
Code:
Private Function GetFileHandle(FileName As String, bRead As Boolean) As Long
' Function uses APIs to read/create files with unicode support
Const GENERIC_READ As Long = &H80000000
Const OPEN_EXISTING = &H3
Const FILE_SHARE_READ = &H1
Const GENERIC_WRITE As Long = &H40000000
Const FILE_SHARE_WRITE As Long = &H2
Const CREATE_ALWAYS As Long = 2
Const FILE_ATTRIBUTE_ARCHIVE As Long = &H20
Const FILE_ATTRIBUTE_HIDDEN As Long = &H2
Const FILE_ATTRIBUTE_READONLY As Long = &H1
Const FILE_ATTRIBUTE_SYSTEM As Long = &H4
Const FILE_ATTRIBUTE_NORMAL = &H80&
Dim Flags As Long, Access As Long
Dim Disposition As Long, Share As Long, hFile As Long
Dim bUnicode As Boolean
bUnicode = Not (IsWindowUnicode(GetDesktopWindow) = 0&)
If bRead Then
Access = GENERIC_READ
Share = FILE_SHARE_READ
Disposition = OPEN_EXISTING
Flags = FILE_ATTRIBUTE_ARCHIVE Or FILE_ATTRIBUTE_HIDDEN Or FILE_ATTRIBUTE_NORMAL _
Or FILE_ATTRIBUTE_READONLY Or FILE_ATTRIBUTE_SYSTEM
Else
Access = GENERIC_READ Or GENERIC_WRITE
Share = 0&
If bUnicode Then
Flags = GetFileAttributesW(StrPtr(FileName))
If (Flags And FILE_ATTRIBUTE_READONLY) Then
Flags = FILE_ATTRIBUTE_NORMAL
SetFileAttributesW StrPtr(FileName), Flags
End If
Else
Flags = GetFileAttributes(FileName)
If (Flags And FILE_ATTRIBUTE_READONLY) Then
Flags = FILE_ATTRIBUTE_NORMAL
SetFileAttributes FileName, Flags
End If
End If
If Flags < 0& Then Flags = FILE_ATTRIBUTE_NORMAL
' CREATE_ALWAYS will delete previous file if necessary
Disposition = CREATE_ALWAYS
End If
If bUnicode Then
hFile = CreateFileW(StrPtr(FileName), Access, Share, ByVal 0&, Disposition, Flags, 0&)
If hFile = 0& Then hFile = INVALID_HANDLE_VALUE
Else
hFile = CreateFile(FileName, Access, Share, ByVal 0&, Disposition, Flags, 0&)
If hFile = 0& Then hFile = INVALID_HANDLE_VALUE
End If
GetFileHandle = hFile
End Function
' changes to your routine
Public Function GetBin(ByVal lpFileName As String, ByVal lpByteCount As Long, Optional ByVal StartByte As Long = 0) As String
On Error Resume Next
Dim Bin() As Byte
Dim ByteSum As Long
Dim i As Long
Dim hFile As Long, lNrRead As Long
hFile = GetFileHandle(lpFileName, True)
If hFile = INVALID_HANDLE_VALUE Then
MsgBox "Failed to access the passed file name"
Else
ReDim Bin(lpByteCount) As Byte
SetFilePointer hFile, 0&, 0&, ByVal 0& ' beginning of file
ReadFile hFile, Bin(0), lpByteCount, lNrRead, ByVal 0&
CloseHandle hFile
If lpByteCount < lNrRead Then
MsgBox "Not all data was read."
' Reasons: 1) StartByte > FileLength, 2) lbByteCount+StartByte > FileLength, 3) other
Else
For i = 0 To lpByteCount
ByteSum = ByteSum + Bin(i)
Next i
GetBin = ByteSum
End If
End If
End Function
Here are the API declarations. To get more details about the APIs recommend reading about them on MSDN or AllAPI.net
Code:
Private Declare Function IsWindowUnicode Lib "user32.dll" (ByVal hWnd As Long) As Long
Private Declare Function GetDesktopWindow Lib "user32.dll" () As Long
Private Declare Function ReadFile Lib "kernel32.dll" (ByVal hFile As Long, ByRef lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, ByRef lpNumberOfBytesRead As Long, ByRef lpOverlapped As Any) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Any) As Long
Private Declare Function CreateFileW Lib "kernel32" (ByVal lpFileName As Long, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function DeleteFileW Lib "kernel32.dll" (ByVal lpFileName As Long) As Long
Private Declare Function DeleteFileA Lib "kernel32.dll" (ByVal lpFileName As String) As Long
Private Declare Function SetFileAttributesW Lib "kernel32.dll" (ByVal lpFileName As Long, ByVal dwFileAttributes As Long) As Long
Private Declare Function SetFileAttributes Lib "kernel32.dll" Alias "SetFileAttributesA" (ByVal lpFileName As String, ByVal dwFileAttributes As Long) As Long
Private Declare Function GetFileAttributesW Lib "kernel32.dll" (ByVal lpFileName As Long) As Long
Private Declare Function GetFileAttributes Lib "kernel32.dll" Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long
Private Declare Function GetFileSize Lib "kernel32.dll" (ByVal hFile As Long, ByVal lpFileSizeHigh As Long) As Long
Private Declare Function SetFilePointer Lib "kernel32.dll" (ByVal hFile As Long, ByVal lDistanceToMove As Long, ByRef lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Const INVALID_HANDLE_VALUE = -1&
Last edited by LaVolpe; Dec 31st, 2009 at 07:15 PM.
-
Jan 4th, 2010, 04:40 AM
#5
Thread Starter
Member
-
Jan 4th, 2010, 09:03 AM
#6
Re: [HELP] Unicode problem: read binary file at spesific position with unicode path
You are welcome. In order to use your optional StartByte parameter, suggest changing related line to:
SetFilePointer hFile, startByte, 0&, ByVal 0&
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|