Поиск…


Синтаксис

  • int readfile (строка $ filename [, bool $ use_include_path = false [, resource $ context]])

параметры

параметр Описание
имя файла Чтение имени файла.
use_include_path Вы можете использовать необязательный второй параметр и установить его в ИСТИНА, если вы хотите также искать файл в include_path.
контекст Ресурс контекстного потока.

замечания

Синтаксис имени файла

Большинство имен файлов, переданных в функции в этом разделе:

  1. Строки в природе.
    • Имена файлов могут передаваться напрямую. Если передаются значения других типов, они передаются в строку. Это особенно полезно с SplFileInfo , которое является значением в итерации DirectoryIterator .
  2. Относительный или абсолютный.
    • Они могут быть абсолютными. В Unix-подобных системах абсолютные пути начинаются с / , например /home/user/file.txt , тогда как в Windows абсолютные пути начинаются с диска, например C:/Users/user/file.txt
    • Они также могут быть относительными, что зависит от значения getcwd и может быть изменено chdir .
  3. Принимать протоколы.
    • Они могут начинаться со scheme:// для указания обертки протокола для управления. Например, file_get_contents("http://example.com") извлекает контент с сайта http://example.com .
  4. Slash-совместимый.
    • Хотя DIRECTORY_SEPARATOR в Windows - это обратная косая черта, и система по умолчанию возвращает обратную косую черту по умолчанию, разработчик все еще может использовать / в качестве разделителя каталогов. Поэтому для совместимости разработчики могут использовать / как разделители каталогов во всех системах, но имейте в виду, что значения, возвращаемые функциями (например, realpath ), могут содержать обратную косую черту.

Удаление файлов и каталогов

Удаление файлов

Функция unlink удаляет один файл и возвращает, была ли операция успешной.

$filename = '/path/to/file.txt';

if (file_exists($filename)) {
    $success = unlink($filename);
    
    if (!$success) {
         throw new Exception("Cannot delete $filename");
    }
}

Удаление каталогов с рекурсивным удалением

С другой стороны, каталоги должны быть удалены с помощью rmdir . Однако эта функция удаляет только пустые каталоги. Чтобы удалить каталог с файлами, сначала удалите файлы в каталогах. Если каталог содержит подкаталоги, может потребоваться рекурсия .

Следующий пример сканирует файлы в каталоге, рекурсивно удаляет файлы-члены / каталоги и возвращает количество удаленных файлов (не каталогов).

function recurse_delete_dir(string $dir) : int {
    $count = 0;

    // ensure that $dir ends with a slash so that we can concatenate it with the filenames directly
    $dir = rtrim($dir, "/\\") . "/";

    // use dir() to list files
    $list = dir($dir);

    // store the next file name to $file. if $file is false, that's all -- end the loop.
    while(($file = $list->read()) !== false) {
        if($file === "." || $file === "..") continue;
        if(is_file($dir . $file)) {
            unlink($dir . $file);
            $count++;
        } elseif(is_dir($dir . $file)) {
            $count += recurse_delete_dir($dir . $file);
        }
    }

    // finally, safe to delete directory!
    rmdir($dir);

    return $count;
}

Удобные функции

Прямой прямой ввод-вывод

file_get_contents и file_put_contents предоставляют возможность чтения / записи из / в файл в / из строки PHP за один раз.

file_put_contents также могут использоваться с флагом FILE_APPEND чтобы добавить, а не FILE_APPEND и перезаписать файл. Он может использоваться вместе с LOCK_EX для получения эксклюзивной блокировки файла при переходе к записи. Флаги битмаски могут быть объединены с | бит-OR.

$path = "file.txt";
// reads contents in file.txt to $contents
$contents = file_get_contents($path);
// let's change something... for example, convert the CRLF to LF!
$contents = str_replace("\r\n", "\n", $contents);
// now write it back to file.txt, replacing the original contents
file_put_contents($path, $contents);

FILE_APPEND удобен для добавления файлов журнала, в то время как LOCK_EX помогает предотвратить состояние гонки при записи файлов из нескольких процессов. Например, чтобы записать в файл журнала о текущем сеансе:

file_put_contents("logins.log", "{$_SESSION["username"]} logged in", FILE_APPEND | LOCK_EX);

CSV IO

fgetcsv($file, $length, $separator)

fgetcsv анализирует строку из проверки открытых файлов для полей csv. Он возвращает поля CSV в массиве с успехом или FALSE при сбое.

По умолчанию он будет читать только одну строку файла CSV.

$file = fopen("contacts.csv","r");
print_r(fgetcsv($file));    
print_r(fgetcsv($file,5," "));
fclose($file); 

contacts.csv

Kai Jim, Refsnes, Stavanger, Norway
Hege, Refsnes, Stavanger, Norway

Выход:

Array
(
    [0] => Kai Jim
    [1] => Refsnes
    [2] => Stavanger
    [3] => Norway
)
Array
(
    [0] => Hege,
)

Чтение файла прямо в stdout

readfile копирует файл в выходной буфер. readfile () не представляет проблем с памятью, даже при отправке больших файлов, сам по себе.

$file = 'monkey.gif';

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="'.basename($file).'"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    readfile($file);
    exit;
}

Или из указателя файла

В качестве альтернативы, чтобы найти точку в файле, чтобы начать копирование в stdout, вместо этого используйте fpassthru . В следующем примере последние 1024 байта копируются в stdout:

$fh = fopen("file.txt", "rb");
fseek($fh, -1024, SEEK_END); 
fpassthru($fh);

Чтение файла в массив

file возвращает строки в переданном файле в массиве. Каждый элемент массива соответствует строке в файле, а новая строка все еще прикреплена.

print_r(file("test.txt"));

test.txt

Welcome to File handling
This is to test file handling

Выход:

Array 
( 
    [0] => Welcome to File handling 
    [1] => This is to test file handling 
)

Получение информации о файле

Проверьте, является ли путь каталогом или файлом

Функция is_dir возвращает, является ли аргумент каталогом, а is_file возвращает, является ли аргумент файлом. Используйте file_exists чтобы проверить, есть ли это.

$dir  = "/this/is/a/directory";
$file = "/this/is/a/file.txt";

echo is_dir($dir) ? "$dir is a directory" : "$dir is not a directory", PHP_EOL,
    is_file($dir) ? "$dir is a file" : "$dir is not a file", PHP_EOL,
    file_exists($dir) ? "$dir exists" : "$dir doesn't exist", PHP_EOL,
    is_dir($file) ? "$file is a directory" : "$file is not a directory", PHP_EOL,
    is_file($file) ? "$file is a file" : "$file is not a file", PHP_EOL,
    file_exists($file) ? "$file exists" : "$file doesn't exist", PHP_EOL;

Это дает:

/this/is/a/directory is a directory
/this/is/a/directory is not a file
/this/is/a/directory exists
/this/is/a/file.txt is not a directory
/this/is/a/file.txt is a file
/this/is/a/file.txt exists

Проверка типа файла

Используйте filetype для проверки типа файла, который может быть:

  • fifo
  • char
  • dir
  • block
  • link
  • file
  • socket
  • unknown

Передача имени файла в filetype файла напрямую:

echo filetype("~"); // dir

Обратите внимание, что filetype возвращает false и запускает E_WARNING если файл не существует.

Проверка читаемости и возможности записи

Передача имени файла в функции is_writable и is_readable проверяет, доступен ли файл для записи или чтения.

Функции возвращают false изящно, если файл не существует.

Проверка времени доступа к файлу / изменения времени

Использование filemtime и fileatime возвращает метку времени последней модификации или доступа к файлу. Возвращаемое значение - это отметка времени Unix - подробности см. В разделе Работа с датами и временем .

echo "File was last modified on " . date("Y-m-d", filemtime("file.txt"));
echo "File was last accessed on " . date("Y-m-d", fileatime("file.txt"));

Получить части пути с помощью fileinfo

$fileToAnalyze = ('/var/www/image.png');

$filePathParts = pathinfo($fileToAnalyze);

echo '<pre>';
   print_r($filePathParts);
echo '</pre>';

В этом примере будет выводиться:

Array
(
    [dirname] => /var/www
    [basename] => image.png
    [extension] => png
    [filename] => image
)

Который может использоваться как:

$filePathParts['dirname']
$filePathParts['basename']
$filePathParts['extension']
$filePathParts['filename']
параметр подробности
$ путь Полный путь к файлу, который нужно разобрать
$ опция Один из четырех доступных опций [PATHINFO_DIRNAME, PATHINFO_BASENAME, PATHINFO_EXTENSION или PATHINFO_FILENAME]
  • Если параметр (второй параметр) не передается, ассоциативный массив возвращается, иначе возвращается строка.
  • Не подтверждает, что файл существует.
  • Просто анализирует строку на части. В файле не выполняется проверка (нет проверки типа mime и т. Д.).
  • Расширение - это просто последнее расширение $path . Путь к файлу image.jpg.png будет .png даже если это технически файл .jpg . Файл без расширения не возвращает элемент расширения в массиве.

Минимизировать использование памяти при работе с большими файлами

Если нам нужно проанализировать большой файл, например, CSV более 10 Мбайт, содержащий миллионы строк, некоторые используют функции file или file_get_contents и заканчивают тем, что memory_limit параметр memory_limit с помощью

Допустимый размер памяти XXXXX байт исчерпан

ошибка. Рассмотрим следующий источник (top-1m.csv имеет ровно 1 миллион строк и составляет около 22 Мбайт)

var_dump(memory_get_usage(true));
$arr = file('top-1m.csv');
var_dump(memory_get_usage(true));

Эти результаты:

int(262144)
int(210501632) 

потому что интерпретатору необходимо было держать все строки в $arr массиве, поэтому он потреблял ~ 200 Мбайт ОЗУ. Обратите внимание, что мы ничего не сделали с содержимым массива.

Теперь рассмотрим следующий код:

var_dump(memory_get_usage(true));
$index = 1;
if (($handle = fopen("top-1m.csv", "r")) !== FALSE) {
    while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) {
        file_put_contents('top-1m-reversed.csv',$index . ',' . strrev($row[1]) . PHP_EOL, FILE_APPEND);
        $index++;
    }
    fclose($handle);
}
var_dump(memory_get_usage(true));

которые выходят

int(262144)
int(262144)

поэтому мы не используем один лишний байт памяти, а анализируем весь CSV и сохраняем его в другом файле, изменяя значение второго столбца. Это потому, что fgetcsv читает только одну строку, а $row перезаписывается в каждом цикле.

Файл ввода-вывода с потоком

Открытие потока

fopen открывает дескриптор потока файлов, который может использоваться с различными функциями для чтения, записи, поиска и других функций поверх него. Это значение относится к типу resource и не может быть передано другим потокам, сохраняющим свою функциональность.

$f = fopen("errors.log", "a"); // Will try to open errors.log for writing

Второй параметр - это режим файлового потока:

Режим Описание
r Открыть в режиме только для чтения, начиная с начала файла
r+ Открыть для чтения и записи, начиная с начала файла
w открыт только для записи, начиная с начала файла. Если файл существует, он очистит файл. Если он не существует, он попытается создать его.
w+ открыт для чтения и записи, начиная с начала файла. Если файл существует, он очистит файл. Если он не существует, он попытается создать его.
a откройте файл только для записи, начиная с конца файла. Если файл не существует, он попытается создать его
a+ откройте файл для чтения и записи, начиная с конца файла. Если файл не существует, он попытается создать его
x создавать и открывать файл только для записи. Если файл существует, вызов fopen не будет завершен
x+ создавать и открывать файл для чтения и записи. Если файл существует, вызов fopen не будет завершен
c откройте файл только для записи. Если файл не существует, он попытается его создать. Он начнет писать в начале файла, но не удалит файл перед записью
c+ откройте файл для чтения и записи. Если файл не существует, он попытается его создать. Он начнет писать в начале файла, но не удалит файл перед записью

Добавление t за режим (например, a+b , wt и т. Д.) В Windows приведет к переводу окончаний строки "\n" на "\r\n" при работе с файлом. Добавьте b за режим, если это не предназначено, особенно если это двоичный файл.

Приложение PHP должно закрывать потоки, используя fclose когда они больше не используются для предотвращения Too many open files ошибок Too many open files . Это особенно важно в программах CLI, поскольку потоки закрываются только тогда, когда среда выполнения отключается - это означает, что на веб-серверах это может быть необязательно (но все же должно быть , как практика предотвращения утечки ресурсов), чтобы закрыть потоки если вы не ожидаете, что процесс будет работать в течение длительного времени и не откроет много потоков.

чтение

Использование fread будет считывать заданное количество байтов из указателя файла или до тех пор, пока не будет выполняться EOF.

Линии чтения

Использование fgets будет читать файл до тех пор, пока не будет достигнут EOL, или данная длина будет считана.

Как fread и fgets будут перемещать указатель файла во время чтения.

Чтение всего остального

Использование stream_get_contents будет stream_get_contents все оставшиеся байты в потоке в строку и вернуть ее.

Настройка позиции указателя на файл

Первоначально после открытия потока указатель файла находится в начале файла (или в конце, если используется режим a ). Использование функции fseek переместит указатель файла на новую позицию относительно одного из трех значений:

  • SEEK_SET : это значение по умолчанию; смещение позиции файла будет относиться к началу файла.
  • SEEK_CUR : смещение позиции файла будет относительно текущей позиции.
  • SEEK_END : смещение позиции файла будет относиться к концу файла. Передача отрицательного смещения является наиболее распространенным использованием для этого значения; он переместит позицию файла в указанное количество байт до конца файла.

rewind - это удобный ярлык для fseek($fh, 0, SEEK_SET) .

Использование ftell покажет абсолютную позицию указателя файла.

Например, следующий скрипт читает пропускает первые 10 байт, читает следующие 10 байт, пропускает 10 байтов, читает следующие 10 байт, а затем последние 10 байтов в файле .txt:

$fh = fopen("file.txt", "rb");
fseek($fh, 10); // start at offset 10
echo fread($fh, 10); // reads 10 bytes
fseek($fh, 10, SEEK_CUR); // skip 10 bytes
echo fread($fh, 10); // read 10 bytes
fseek($fh, -10, SEEK_END); // skip to 10 bytes before EOF
echo fread($fh, 10); // read 10 bytes
fclose($fh);

Пишу

Использование fwrite записывает предоставленную строку в файл, начинающийся с текущего указателя файла.

fwrite($fh, "Some text here\n");

Перемещение и копирование файлов и каталогов

Копирование файлов

copy копирует исходный файл в первом аргументе к месту назначения во втором аргументе. Разрешенное место назначения должно быть в каталоге, который уже создан.

if (copy('test.txt', 'dest.txt')) {
    echo 'File has been copied successfully';
} else {
    echo 'Failed to copy file to destination given.'
}

Копирование каталогов с рекурсией

Копирование каталогов во многом аналогично удалению каталогов, за исключением того, что для copy файлов используется вместо unlink , тогда как для каталогов используется mkdir вместо rmdir , в начале вместо того, чтобы быть в конце функции.

function recurse_delete_dir(string $src, string $dest) : int {
    $count = 0;

    // ensure that $src and $dest end with a slash so that we can concatenate it with the filenames directly
    $src = rtrim($dest, "/\\") . "/";
    $dest = rtrim($dest, "/\\") . "/";

    // use dir() to list files
    $list = dir($src);

    // create $dest if it does not already exist
    @mkdir($dest);

    // store the next file name to $file. if $file is false, that's all -- end the loop.
    while(($file = $list->read()) !== false) {
        if($file === "." || $file === "..") continue;
        if(is_file($src . $file)) {
            copy($src . $file, $dest . $file);
            $count++;
        } elseif(is_dir($src . $file)) {
            $count += recurse_copy_dir($src . $file, $dest . $file);
        }
    }

    return $count;
}

Переименование / Перемещение

Переименование / перемещение файлов и каталогов намного проще. Целые каталоги могут быть перемещены или переименованы в один вызов, используя функцию rename .

  • rename("~/file.txt", "~/file.html");

  • rename("~/dir", "~/old_dir");

  • rename("~/dir/file.txt", "~/dir2/file.txt");



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow