Поделиться через


Функция SetFilePointer (fileapi.h)

Перемещает указатель на указанный файл.

Эта функция сохраняет указатель на файл в двух значениях LONG . Для работы с указателями файлов, размер которых превышает одно значение LONG , проще использовать функцию SetFilePointerEx .

Синтаксис

DWORD SetFilePointer(
  [in]                HANDLE hFile,
  [in]                LONG   lDistanceToMove,
  [in, out, optional] PLONG  lpDistanceToMoveHigh,
  [in]                DWORD  dwMoveMethod
);

Параметры

[in] hFile

Дескриптор файла.

Дескриптор файла должен быть создан с правом доступа GENERIC_READ или GENERIC_WRITE . Дополнительные сведения см. в разделе Безопасность файлов и права доступа.

[in] lDistanceToMove

32-разрядное значение со знаком нижнего порядка, указывающее количество байтов для перемещения указателя на файл.

Если значение lpDistanceToMoveHigh не равно NULL, lpDistanceToMoveHigh и lDistanceToMove образуют одно 64-разрядное значение со знаком, указывающее расстояние для перемещения.

Если lpDistanceToMoveHigh имеет значение NULL, lDistanceToMove — 32-разрядное значение со знаком. Положительное значение для lDistanceToMove перемещает указатель файла вперед в файле, а отрицательное значение — назад.

[in, out, optional] lpDistanceToMoveHigh

Указатель на 32-разрядную высоту 64-разрядного расстояния со знаком для перемещения.

Если 32-разрядные разряды высокого порядка не требуются, для этого указателя необходимо задать значение NULL.

Если значение не равно NULL, этот параметр также получает DWORD высокого порядка нового значения указателя файла. Дополнительные сведения см. в разделе Примечания этой статьи.

[in] dwMoveMethod

Начальная точка перемещения указателя файла.

Этот параметр может принимать одно из указанных ниже значений.

Значение Значение
FILE_BEGIN
0
Начальная точка равна нулю или началу файла.
FILE_CURRENT
1
Начальной точкой является текущее значение указателя файла.
FILE_END
2
Отправной точкой является текущая позиция конца файла.

Возвращаемое значение

Если функция выполнена успешно и lpDistanceToMoveHigh имеет значение NULL, возвращаемое значение представляет собой значение DWORD нижнего порядка нового указателя файла. Примечание Если функция возвращает значение, отличное от INVALID_SET_FILE_POINTER, вызов SetFilePointer выполнен успешно. Не нужно вызывать GetLastError.

Если функция выполнена успешно и lpDistanceToMoveHigh не равно NULL, возвращаемое значение — это значение DWORD нижнего порядка нового указателя файла, а lpDistanceToMoveHigh содержит DWORD высокого порядка нового указателя файла.

Если функция завершается сбоем, возвращаемое значение будет INVALID_SET_FILE_POINTER. Дополнительные сведения об ошибке можно получить, вызвав GetLastError.

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

Если lpDistanceToMoveHigh имеет значение NULL и новая позиция файла не помещается в 32-разрядное значение, функция завершается ошибкой и возвращает INVALID_SET_FILE_POINTER.

Примечание Так как INVALID_SET_FILE_POINTER является допустимым значением для DWORD нижнего порядка нового указателя файла, необходимо проверка возвращаемое значение функции и код ошибки, возвращаемый Командлетом GetLastError, чтобы определить, произошла ли ошибка. Если произошла ошибка, возвращается значение SetFilePointerINVALID_SET_FILE_POINTER , а GetLastError возвращает значение, отличное от NO_ERROR. Пример кода, демонстрирующий, как проверка из-за сбоя, см. в разделе Примечания этого раздела.
 

Комментарии

Указатель на файл, определяемый значением параметра hFile , не используется для перекрывающихся операций чтения и записи.

Параметр hFile должен ссылаться на файл, хранящийся на устройстве поиска; например, том диска. Вызов функции SetFilePointer с дескриптором к устройству без поиска, такому как канал или устройство связи, не поддерживается, хотя функция SetFilePointer может не возвращать ошибку. Поведение функции SetFilePointer в этом случае не определено.

Задание смещения для перекрывающихся операций

  • Используйте элементы Offset и OffsetHigh структуры OVERLAPPED .

Определение типа файла для hFile

Сведения об определении положения указателя на файл см. в разделе Позиционирование указателя на файл.

Будьте внимательны при установке указателя на файл в многопотоковом приложении. Необходимо синхронизировать доступ к общим ресурсам. Например, приложение с потоками, которые совместно используют дескриптор файла, обновляют указатель файла и считывают данные из файла, должны защищать эту последовательность с помощью объекта критического раздела или объекта мьютекса. Дополнительные сведения см. в разделе Объекты критического раздела и объекты мьютексов.

Если дескриптор hFile открыт с установленным флагом FILE_FLAG_NO_BUFFERING , приложение может переместить указатель на файл только в положение, выровненное по секторам. Позиция, выравниваемая по секторам, — это позиция, которая является целым числом, кратным размеру сектора тома. Приложение может получить размер сектора тома, вызвав функцию GetDiskFreeSpace .

Если приложение вызывает SetFilePointer с расстоянием для перемещения значений, что приводит к позиции, не выровненной по секторам, и дескриптор, открытый с помощью FILE_FLAG_NO_BUFFERING, функция завершается сбоем, и GetLastError возвращает ERROR_INVALID_PARAMETER.

Установка указателя на файл на позицию за пределами конца файла не является ошибкой. Размер файла не увеличивается, пока вы не вызовете функцию SetEndOfFile, WriteFile или WriteFileEx . Операция записи увеличивает размер файла до позиции указателя файла плюс размер записанного буфера, что приводит к нулевой инициализации промежуточных байтов.

Если возвращаемое значение INVALID_SET_FILE_POINTER , а значение lpDistanceToMoveHigh не равно NULL, приложение должно вызвать Метод GetLastError , чтобы определить, успешно ли выполнена функция. В следующем примере кода показан этот сценарий.

  // Case One: calling the function with lpDistanceToMoveHigh == NULL 

  // Try to move hFile file pointer some distance  
  DWORD dwPtr = SetFilePointer( hFile, 
                                lDistance, 
                                NULL, 
                                FILE_BEGIN ); 
   
  if (dwPtr == INVALID_SET_FILE_POINTER) // Test for failure
   { 
    // Obtain the error code. 
    DWORD dwError = GetLastError() ; 
   
    // Deal with failure 
    // . . . 
   
   } // End of error handler 


  //
  // Case Two: calling the function with lpDistanceToMoveHigh != NULL

  // Try to move hFile file pointer a huge distance 
  DWORD dwPtrLow = SetFilePointer( hFile, 
                                   lDistLow, 
                                   &lDistHigh, 
                                   FILE_BEGIN ); 
   
  // Test for failure
  if ( dwPtrLow == INVALID_SET_FILE_POINTER && 
       GetLastError() != NO_ERROR )
   {
    // Deal with failure
    // . . .

   } // End of error handler

Хотя параметр lpDistanceToMoveHigh используется для управления большими файлами, значение параметра следует задавать при перемещении файлов любого размера. Если задано значение NULL, то lDistanceToMove имеет максимальное значение 2^31–2 или 2 гигабайта меньше 2, так как все значения указателя файла являются значениями со знаком. Поэтому, если существует даже небольшая вероятность увеличения файла до этого размера, лучше рассматривать файл как огромный файл и работать с 64-разрядными указателями на файл. При сжатии файлов в файловой системе NTFS и разреженных файлах можно иметь большие файлы, даже если базовый том не очень большой.

Если lpDistanceToMoveHigh не равно NULL, то lpDistanceToMoveHigh и lDistanceToMove образуют одно 64-разрядное значение со знаком. Параметр lDistanceToMove обрабатывается как низкий порядок 32 бита значения, а lpDistanceToMoveHigh — как 32 бита высокого порядка, что означает, что lpDistanceToMoveHigh является расширением знака lDistanceToMove.

Чтобы переместить указатель на файл с нуля на 2 гигабайта, lpDistanceToMoveHigh необходимо задать значение NULL или расширение знака lDistanceToMove. Чтобы переместить указатель более чем на 2 гигабайта, используйте lpDistanceToMoveHigh и lDistanceToMove в качестве одного 64-разрядного количества. Например, для перемещения в диапазоне от 2 гигабайт до 4 гигабайт задайте для содержимого lpDistanceToMoveHigh значение 0 или –1 для расширения отрицательного знака lDistanceToMove.

Для работы с 64-разрядными указателями на файл можно объявить long, считать его верхней половиной 64-разрядного указателя на файл и передать его адрес в lpDistanceToMoveHigh. Это означает, что необходимо рассматривать две разные переменные как логическую единицу, что может привести к ошибке. Лучше всего использовать структуру LARGE_INTEGER для создания 64-разрядного значения и передачи двух 32-разрядных значений с помощью соответствующих элементов объединения.

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

__int64 myFileSeek (HANDLE hf, __int64 distance, DWORD MoveMethod)
{
   LARGE_INTEGER li;

   li.QuadPart = distance;

   li.LowPart = SetFilePointer (hf, 
                                li.LowPart, 
                                &li.HighPart, 
                                MoveMethod);

   if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() 
       != NO_ERROR)
   {
      li.QuadPart = -1;
   }

   return li.QuadPart;
}

Для определения длины файла можно использовать SetFilePointer . Для этого используйте FILE_END для dwMoveMethod и найдите нулевое расположение. Возвращенное смещение файла — это длина файла. Однако такой подход может иметь непреднамеренные побочные эффекты, например сбой при сохранении текущего указателя файла, чтобы программа вернется в это расположение. Лучше всего использовать GetFileSize .

Вы также можете использовать функцию SetFilePointer для запроса текущей позиции указателя файла. Для этого укажите метод перемещения FILE_CURRENT и нулевое расстояние.

В Windows 8 и Windows Server 2012 эта функция поддерживается следующими технологиями.

Технология Поддерживается
Протокол SMB 3.0 Да
SMB 3.0 Transparent Failover (TFO) Да
SMB 3.0 с масштабируемыми общими папками (SO) Да
Файловая система общего тома кластера (CSVFS) Да
Восстанавливаемая файловая система (ReFS) Да
 

Примеры

Пример кода добавления файлов см. в разделе Добавление одного файла в другой файл.

Требования

Требование Значение
Минимальная версия клиента Windows XP [классические приложения | Приложения UWP]
Минимальная версия сервера Windows Server 2003 [классические приложения | Приложения UWP]
Целевая платформа Windows
Header fileapi.h (включая Windows.h)
Библиотека Kernel32.lib
DLL Kernel32.dll

См. также

Функции управления файлами

GetDiskFreeSpace

GetFileSize

GetFileType

ReadFile

ReadFileEx

SetEndOfFile

SetFilePointerEx

WriteFile

WriteFileEx