Получение байта в большом файле

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
13GHOST
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 305
Зарегистрирован: 09.01.2004 (Пт) 12:48

Получение байта в большом файле

Сообщение 13GHOST » 09.04.2009 (Чт) 14:12

Вообщем делаю так:
Код: Выделить всё
i = FreeFile
Open strFullPath For Binary Access Read As #i
Buffer = Space$(bSize)
Get #i, curbyte, Buffer
....

размер файла strFullPath - 2201157632 байт
curbyte = 2147479552
bSize = 4096
Вылетает на Get #i, curbyte, Buffer. Пишет Bad record Number. В чем проблема? что curbyte должен быть в пределах Long обязательно?
да этого чтение файла идет номрально но как только curbyte становится таким - вылетает :(

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Получение байта в большом файле

Сообщение alibek » 09.04.2009 (Чт) 14:50

13GHOST писал(а):что curbyte должен быть в пределах Long обязательно?

Да.
Используй API и 64-разрядные указатели.
Lasciate ogni speranza, voi ch'entrate.

13GHOST
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 305
Зарегистрирован: 09.01.2004 (Пт) 12:48

Re: Получение байта в большом файле

Сообщение 13GHOST » 09.04.2009 (Чт) 14:56

а какие АПИ есть в этой теме? можно уточнить?

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Получение байта в большом файле

Сообщение alibek » 09.04.2009 (Чт) 15:35

CreateFile/ReadFileEx.
Lasciate ogni speranza, voi ch'entrate.

13GHOST
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 305
Зарегистрирован: 09.01.2004 (Пт) 12:48

Re: Получение байта в большом файле

Сообщение 13GHOST » 10.04.2009 (Пт) 15:24

большое спасибо

13GHOST
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 305
Зарегистрирован: 09.01.2004 (Пт) 12:48

Re: Получение байта в большом файле

Сообщение 13GHOST » 11.04.2009 (Сб) 19:22

не получается никак совладать с ReadFileEx
Делаю так:
Код: Выделить всё
Private bytes(4098) as Byte
Private ol As OVERLAPPED
...
hFile = CreateFile(strFullPath, GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0)
ReadFileEx hFile, bytes(0), 4098, ol, AddressOf FileIOCompletionRoutine
...

Public Sub FileIOCompletionRoutine(ByVal dwErrorCode As Long, ByVal dwNumberOfBytesTransfered As Long, ol As OVERLAPPED)
ol.offset = ol.offset + dwNumberOfBytesTransfered
End Sub


После чего в Bytes есть какие то данные, но не те, которые там на самом деле. Т.е. Get #i, ,buffer возвращает в Buffer другие данные :(. В чем может быть проблема? И есть ли у кого-нить пример работы с readfileex/writefileex ?

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Получение байта в большом файле

Сообщение alibek » 11.04.2009 (Сб) 19:31

Во-первых, количество байт 4099.
Во-вторых, покажи весь код, с декларациями.
Lasciate ogni speranza, voi ch'entrate.

13GHOST
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 305
Зарегистрирован: 09.01.2004 (Пт) 12:48

Re: Получение байта в большом файле

Сообщение 13GHOST » 11.04.2009 (Сб) 19:47

а все заработало, где то еденичку потерял. А вот еще такой вопрос:
Код: Выделить всё
Public Type OVERLAPPED
    Internal As Long
    InternalHigh As Long
    offset As Long
    OffsetHigh As Long
    hEvent As Long
End Type

Дак ведь в этой сктруре параметр offset, который задает позицию чтения тоже в LONG. Как быть?

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Получение байта в большом файле

Сообщение iGrok » 11.04.2009 (Сб) 20:10

13GHOST писал(а):..Дак ведь в этой сктруре параметр offset, который задает позицию чтения тоже в LONG. Как быть?

Делить 64битный offset на 32бит LOW-DWORD и 32 бит HIGH-DWORD. В Offset писать LOW-DWORD, в OffsetHigh - HIGH-DWORD.

Как раз таким образом эта функция и позволяет читать данные, находящиеся выше 4294967296 байта.

UPD:
А. А тебе нужно читать хотя бы больше 2147483647 байт. Гм.. А в VB ведь нету Unsigned Long.. А действительно, как?

Первое предположение, писать в Long нужное значение в HEX (&H...) забив на то, что для VB оно будет отрицательным, и передавать его ReadFileEx в надежде, что оно будет правильно обработано.
label:
cli
jmp label

13GHOST
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 305
Зарегистрирован: 09.01.2004 (Пт) 12:48

Re: Получение байта в большом файле

Сообщение 13GHOST » 11.04.2009 (Сб) 20:16

а как разделить? есть уже написанная функция?
есть currency

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Получение байта в большом файле

Сообщение iGrok » 11.04.2009 (Сб) 20:43

13GHOST писал(а):а как разделить? есть уже написанная функция?
есть currency


Как-то так..
Код: Выделить всё
Public Type UDT_C
    c As Currency
End Type

Public Type UDT_2L
    dwLow As Long
    dwHigh As Long
End Type

Public Sub t1()
Dim c As Currency
Dim uc As UDT_C
Dim u2l As UDT_2L
    c = 4294967296#
    c = c * 2
    Debug.Print c
    uc.c = c / 10000 ' А вот..
    LSet u2l = uc
    Debug.Print "HighDWORD: " & u2l.dwHigh & " LowDWORD: " & u2l.dwLow
End Sub


Правда всё ещё есть сложность со знаковостью лонга.. Впрочем, если считать всё в Currency, а потом вот таким образом переводить - то всё должно работать.
Ну и плюс перед переводом нужно значение в Currency делить на 10000. Вот такой вот у него формат хранения.

UPD:
В целом получается как-то так...
Код: Выделить всё
Option Explicit

Public Type OVERLAPPED
        Internal As Long
        InternalHigh As Long
        Offset As Long
        OffsetHigh As Long
        hEvent As Long
End Type

Public Const GENERIC_READ = &H80000000
Public Const FILE_SHARE_READ = &H1
Public Const OPEN_EXISTING = 3
Public Const FILE_FLAG_OVERLAPPED = &H40000000

Public Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Public Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As OVERLAPPED) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Public Type UDT_C
    c As Currency
End Type

Public Type UDT_2L
    dwLow As Long
    dwHigh As Long
End Type

Public Function Test()
Dim sFileName As String
Dim b() As Byte
    sFileName = "тута было имя файла размером более 5 гигов.."

    If ReadFromFile(sFileName, 4294967296#, 100, b) Then
        Dim i As Long, s As String, ts As String
        For i = 0 To 99
            ts = Hex(b(i))
            s = s & IIf(Len(ts) < 2, String$(2 - Len(ts), "0"), "") & ts
            If (i + 1) Mod 16 = 0 Then s = s & vbCrLf
        Next i
        Debug.Print s
    End If
End Function

Public Function ReadFromFile(sFileName As String, cPos As Currency, ByRef cByteCount As Long, ByRef b() As Byte) As Boolean
Dim hFile As Long, dwRead As Long, hr As Long
Dim uc As UDT_C, ul As UDT_2L, ov As OVERLAPPED

    hFile = CreateFile(sFileName, GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0)

    'ToDo: Проверить hFile на валидность

    uc.c = cPos / 10000
    LSet ul = uc
    ov.Offset = ul.dwLow
    ov.OffsetHigh = ul.dwHigh
    ReDim b(cByteCount - 1)

    hr = ReadFile(hFile, b(0), cByteCount, dwRead, ov)
   
    'ToDo: Проверить hr. Должна быть 1. Иначе - ошибка.
   
    CloseHandle hFile
   
    cByteCount = dwRead
   
    'ToDo: Проверить сколько всего прочитали. Если что - уменьшить b()

    ReadFromFile = True
End Function
Последний раз редактировалось iGrok 11.04.2009 (Сб) 21:04, всего редактировалось 2 раз(а).
label:
cli
jmp label

13GHOST
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 305
Зарегистрирован: 09.01.2004 (Пт) 12:48

Re: Получение байта в большом файле

Сообщение 13GHOST » 11.04.2009 (Сб) 20:54

хм.
Код: Выделить всё
12189934592
HighDWORD: 2 LowDWORD: -694967296


должно быть вроде как: HighDWORD: 2 LowDWORD: 3600000000

это как? конечно может быть -694967296 и есть 3600000000, но это как? readfileex корректно воспримет?

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Получение байта в большом файле

Сообщение iGrok » 11.04.2009 (Сб) 21:01

13GHOST писал(а):хм.
Код: Выделить всё
12189934592
HighDWORD: 2 LowDWORD: -694967296


должно быть вроде как: HighDWORD: 2 LowDWORD: 3600000000

это как? конечно может быть -694967296 и есть 3600000000, но это как? readfileex корректно воспримет?

Корректно.
Я же говорю, в VB нету Unsigned Long.
Посмотри HEX(-694967296), и посмотри (где-нибудь, VB не покажет) HEX(3600000000). Должно совпасть.

З.Ы. Посмотри мой предыдущий пост. Я его немного дополнил.
label:
cli
jmp label

13GHOST
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 305
Зарегистрирован: 09.01.2004 (Пт) 12:48

Re: Получение байта в большом файле

Сообщение 13GHOST » 11.04.2009 (Сб) 21:16

вставил этот код "разложения", но пока протестить не могу т.к. не до конца дописал код. Как сделаю отпишусь :)
дак а чо юзать то? readfile или readfileex?

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Получение байта в большом файле

Сообщение iGrok » 11.04.2009 (Сб) 21:25

13GHOST писал(а):вставил этот код "разложения", но пока протестить не могу т.к. не до конца дописал код. Как сделаю отпишусь :)
дак а чо юзать то? readfile или readfileex?

Для синхронного чтения - ReadFile. Для асинхронного - ReadFileEx.
Обычно асинхронное нафиг не нужно. Опять же, оно усложняет архитектуру приложения (добавляется CallBack - твоя FileIOCompletionRoutine).
Но если нужно читать большие объёмы - лучше асинхронно, чтобы не вешать программу.

З.Ы. Я протестил. Работает. =)
Собственно, полный код парой постов выше и лежит..
label:
cli
jmp label

13GHOST
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 305
Зарегистрирован: 09.01.2004 (Пт) 12:48

Re: Получение байта в большом файле

Сообщение 13GHOST » 11.04.2009 (Сб) 21:54

ок. большое спасибо.
а что понимается под словом синхронно? т.е. в 1 поток?

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Получение байта в большом файле

Сообщение iGrok » 11.04.2009 (Сб) 22:13

13GHOST писал(а):ок. большое спасибо.
а что понимается под словом синхронно? т.е. в 1 поток?

Нет. Грубо:
Синхронно - значит запросили чтение, и выполнение программы останавливается до завершения чтения.
Асинхронно - запросили чтение. И спокойно себе выполняемся дальше. Реагируем на действия пользователя и всё в таком духе.
Когда данные готовы (прочитаны) - происходит событие. В данном случае - вызывается твоя функция.
label:
cli
jmp label

13GHOST
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 305
Зарегистрирован: 09.01.2004 (Пт) 12:48

Re: Получение байта в большом файле

Сообщение 13GHOST » 12.04.2009 (Вс) 8:37

понял. большое спасибо ;)


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: AhrefsBot и гости: 7

    TopList