Мне нужны данные из определенного байта в диапазоне в двоичном файле.
(сцепленные JPEG, не спрашивайте …)
Итак, у меня есть offset
а также length
данные из внешнего API.
(Я бы предположил, что это байтовые позиции)
Что работает, это следующее:
$fileData = file_get_contents($binaryFile);
$imageData = substr($fileData, $offset, $length);
Но я бы предпочел не загружать полный файл в память и поэтому попытался fopen
:
$handle = fopen($binaryFile, 'rb');
fseek($handle, $offset);
$imageData = fgets($handle, $length);
Но это не работает. Блок данных не является действительными данными изображения.
Итак, я полагаю, что я ошибся с позицией fopen
,
Любые идеи о том, как позиции отличаются substr
против fopen
?
Вы написали
Блок данных не является действительными данными изображения
«данные изображения» — но в вашем коде вы называете fgets()
читать эти данные. Это неправильно, поскольку изображение — это двоичные данные, а не текстовый файл, поэтому вы не хотите, чтобы оно читалось по строкам (документы):
fgets — получает линия из файлового указателя
Это означает fgets()
остановит чтение из файла, как только найдет то, что считает маркером конца строки, что обычно означает остановку раньше и чтение меньше, чем $length
так как вероятность того, что такой байт не находится в двоичной последовательности, достаточно мала.
Так fgets()
неправильный метод, и это главная проблема. Вместо этого вы должны выбрать менее умный fread()
(который не знает о строках и прочем и просто читает то, что вы сказали). Наконец вы должны fclose()
ручка, когда вы сделали. И, естественно, вы всегда должны проверять ошибки, начиная с fopen()
:
if ($handle = fopen($binaryFile, 'rb')) {
if (fseek($handle, $offset) === 0) {
$imageData = fread($handle, $length);
if ($imageData === false) {
// error handling - failed to read the data
}
} else {
// error handling - seek failed
}
fclose($handle);
} else {
// error handling - can't open file
}
Поэтому всегда используйте правильный инструмент для задачи, и если вы не уверены, что делает данный метод / функция, всегда есть неплохая документация заглянуть.
Ты можешь использовать file_get_contents
, тоже. Посмотрите на эту простую строку:
imageData = file_get_contents($binaryFile, null, null, 0, $length);
А вот документация file_get_contents.