Seek: примеры (PYTHON)
seek(offset, whence): intОсновы функции seek
seek()
- метод файловых объектов в Python, позволяющий изменять текущую позицию для чтения/записи в файле. Используется при необходимости произвольного доступа к содержимому файла без последовательного чтения всего файла.Применяется при работе с бинарными и текстовыми файлами, когда требуется перейти к определённому фрагменту данных, пропустить часть содержимого или вернуться к ранее прочитанному участку.
Аргументы:
- offset (целое число) - количество байтов для смещения. Может быть положительным (вперед) или отрицательным (назад).
- whence (необязательный, целое число) - точка отсчета смещения:
- 0 (по умолчанию, os.SEEK_SET) - отсчет от начала файла
- 1 (os.SEEK_CUR) - отсчет от текущей позиции
- 2 (os.SEEK_END) - отсчет от конца файла
Возвращаемое значение: новое абсолютное положение в файле (в байтах от начала).
Базовые примеры использования
Пример 1: Смещение от начала файла
with open('test.txt', 'r') as f:
f.seek(10) # Переход к 10-му байту от начала
print(f.read(5))# Выведет 5 символов, начиная с 10-го байта
Пример 2: Смещение от текущей позиции
with open('test.txt', 'rb') as f:
f.read(5) # Читаем первые 5 байт
f.seek(3, 1) # Смещаемся на 3 байта вперед от текущей позиции
print(f.tell()) # Показывает текущую позицию8
Пример 3: Смещение от конца файла
with open('test.txt', 'rb') as f:
f.seek(-5, 2) # 5 байтов от конца файла
print(f.read().decode())# Выведет последние 5 байтов файла
Похожие функции в Python
tell() - возвращает текущую позицию в файле. Часто используется вместе с seek для запоминания и восстановления позиции.
read() и readline() - автоматически изменяют позицию чтения, но без точного контроля смещения.
mmap - модуль для отображения файлов в память, предоставляет более гибкий доступ к данным, но требует больше ресурсов.
Метод seek предпочтительнее при работе с большими файлами, когда требуется доступ к определенным участкам без загрузки всего содержимого в память.
Аналоги в других языках программирования
PHP: fseek() работает аналогично, но возвращает 0 при успехе и -1 при ошибке.
$fp = fopen('test.txt', 'r');
fseek($fp, 10);
echo fread($fp, 5);JavaScript (Node.js): В асинхронном API fs.createReadStream поддерживает опцию start, но нет прямой аналогии seek.
Java: RandomAccessFile.seek() похож на Python-реализацию.
RandomAccessFile file = new RandomAccessFile("test.txt", "r");
file.seek(10);
byte[] bytes = new byte[5];
file.read(bytes);C#: FileStream.Seek() имеет аналогичные параметры.
using (FileStream fs = new FileStream("test.txt", FileMode.Open))
{
fs.Seek(10, SeekOrigin.Begin);
byte[] buffer = new byte[5];
fs.Read(buffer, 0, 5);
}Типичные ошибки
Ошибка 1: Смещение за пределы файла (при whence=0)
with open('test.txt', 'r') as f:
f.seek(1000) # Файл меньше 1000 байт
print(f.read())# Не вызывает ошибку, но последующее чтение вернет пустую строку
Ошибка 2: Отрицательное смещение при отсчете от начала
with open('test.txt', 'r') as f:
f.seek(-5, 0) # ValueErrorValueError: negative seek position
Ошибка 3: Использование с текстовыми файлами и многобайтовыми кодировками
with open('test_utf8.txt', 'r', encoding='utf-8') as f:
f.seek(2) # Может попасть в середину символа UTF-8
print(f.read(1)) # UnicodeDecodeErrorИзменения в последних версиях
В Python 3.1 добавлена возможность использования seek() с аргументом whence как константами модуля os: os.SEEK_SET, os.SEEK_CUR, os.SEEK_END.
В Python 3.3 улучшена работа seek() с файлами, открытыми в текстовом режиме, для файлов, использующих кодировки с переменной длиной символов.
Начиная с Python 3.7, seek() в текстовых файлах поддерживается только для смещений, возвращаемых tell(), или нулевых смещений.
Расширенные примеры использования
Пример 1: Чтение файла с конца
def read_last_lines(filename, n=10):
with open(filename, 'rb') as f:
f.seek(0, 2) # Переход в конец файла
end_pos = f.tell()
lines = []
pos = end_pos
while len(lines) <= n and pos > 0:
pos = max(0, pos - 100)
f.seek(pos)
chunk = f.read(end_pos - pos)
lines = chunk.split(b'\n') + lines
pos -= 100
return b'\n'.join(lines[-n:]).decode()Пример 2: Редактирование бинарного файла
with open('data.bin', 'r+b') as f:
# Замена 4 байтов, начиная с позиции 20
f.seek(20)
original = f.read(4)
print(f"Было: {original}")
f.seek(20) # Возврат к той же позиции
f.write(b'NEW ') # Запись новых данных
f.seek(20)
modified = f.read(4)
print(f"Стало: {modified}")Было: b'OLD ' Стало: b'NEW '
Пример 3: Построчный доступ к большим файлам
def get_line_position(filename, line_num):
positions = [0]
with open(filename, 'r') as f:
while f.readline():
positions.append(f.tell())
if line_num < len(positions):
return positions[line_num]
return None
# Быстрый доступ к строке 1000
pos = get_line_position('large.log', 1000)
if pos is not None:
with open('large.log', 'r') as f:
f.seek(pos)
line = f.readline()
print(f"Строка 1000: {line[:50]}...")