수색…
통사론
- int readfile (string $ filename [, bool $ use_include_path = false [, 리소스 $ 컨텍스트]])
매개 변수
매개 변수 | 기술 |
---|---|
파일 이름 | 읽을 파일 이름입니다. |
use_include_path | include_path에서 파일을 검색하려면 선택적인 두 번째 매개 변수를 사용하고 TRUE로 설정하십시오. |
문맥 | 문맥 스트림 자원. |
비고
파일 이름 구문
이 항목에서 함수에 전달 된 대부분의 파일 이름은 다음과 같습니다.
- 자연 속의 끈.
- 파일 이름은 직접 전달 될 수 있습니다. 다른 유형의 값이 전달되면 문자열로 변환됩니다. 이것은 특히,
DirectoryIterator
반복의 값인SplFileInfo
에서 유용합니다.
- 파일 이름은 직접 전달 될 수 있습니다. 다른 유형의 값이 전달되면 문자열로 변환됩니다. 이것은 특히,
- 상대 또는 절대.
- 프로토콜을 수락하십시오.
- 그들은
scheme://
wrapper로 관리하기 위해scheme://
으로 시작할 수 있습니다. 예를 들어,file_get_contents("http://example.com")
는 http://example.com 에서 콘텐츠를 가져옵니다.
- 그들은
- 슬래시 호환.
- Windows의
DIRECTORY_SEPARATOR
은 백 슬래시이고 시스템은 기본적으로 경로에 백 슬래시를 반환하지만 개발자는/
를 디렉토리 구분 기호로 사용할 수 있습니다. 따라서 호환성을 위해 개발자는/
를 모든 시스템에서 디렉토리 구분 기호로 사용할 수 있지만 함수에서 반환 한 값 (예 :realpath
)에는 백 슬래시가 포함될 수 있습니다.
- Windows의
파일 및 디렉토리 삭제
파일 삭제하기
unlink
함수는 단일 파일을 삭제하고 작업이 성공했는지 여부를 반환합니다.
$filename = '/path/to/file.txt';
if (file_exists($filename)) {
$success = unlink($filename);
if (!$success) {
throw new Exception("Cannot delete $filename");
}
}
재귀 적 삭제로 디렉토리 삭제하기
반면에 rmdir
하여 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;
}
편리한 기능
원시 직접 IO
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
을 사용하여 다음과 같은 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']
매개 변수 | 세부 |
---|---|
$ 경로 | 파싱 할 파일의 전체 경로 |
$ 옵션 | 4 가지 옵션 [PATHINFO_DIRNAME, PATHINFO_BASENAME, PATHINFO_EXTENSION 또는 PATHINFO_FILENAME] 중 하나 |
- 옵션 (두 번째 매개 변수)이 전달되지 않으면 연관 배열이 반환되고 그렇지 않으면 문자열이 반환됩니다.
- 파일이 존재하는지 확인하지 않습니다.
- 문자열을 파트로 파싱하기 만하면됩니다. 파일에 대한 유효성 검사가 수행되지 않습니다 (MIME 유형 검사 등 없음).
- 확장자는 단순히
$path
의 마지막 확장자입니다.image.jpg.png
파일의 경로는 기술적으로.jpg
파일 인 경우에도.png
됩니다. 확장명이없는 파일은 배열의 확장 요소를 반환하지 않습니다.
대용량 파일을 다룰 때 메모리 사용을 최소화하십시오.
수백만 개의 행을 포함하는 10MB 이상의 CSV와 같은 대용량 파일을 구문 분석해야하는 경우 일부는 file
또는 file_get_contents
함수를 사용하여 memory_limit
설정을 사용하여 끝납니다
허용 된 메모리 크기 XXXXX 바이트 만 소모되었습니다.
오류. 다음 소스를 고려하십시오 (top-1m.csv는 정확히 1 백만 행을 가지며 약 22MB 크기 임)
var_dump(memory_get_usage(true));
$arr = file('top-1m.csv');
var_dump(memory_get_usage(true));
이 결과는 다음과 같습니다.
int(262144)
int(210501632)
인터프리터가 $arr
배열의 모든 행을 유지해야하므로 ~ 200MB의 RAM을 소비했습니다. 배열의 내용에 대해서는 아무 것도하지 않았습니다.
이제 다음 코드를 살펴보십시오.
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)
그래서 우리는 여분의 1 바이트의 메모리를 사용하지 않고 전체 CSV를 구문 분석하고 두 번째 열의 값을 반대로 다른 파일에 저장합니다. 왜냐하면 fgetcsv
는 모든 $row
한 행만 읽고 $row
은 덮어 쓰기 때문입니다.
스트림 기반 파일 IO
스트림 열기
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+ | 읽기 및 쓰기 용 파일을 엽니 다. 파일이 존재하지 않으면 생성을 시도합니다. 파일의 시작 부분에 쓰기 시작하지만 쓰기 전에 파일을 비우지 않습니다. |
Windows에서 모드 뒤의 t
(예 : a+b
, wt
등)를 추가하면 파일 작업시 "\n"
줄 끝이 "\r\n"
됩니다. 특히 이진 파일 인 경우 모드를 b
뒤에 추가하십시오.
PHP 응용 프로그램은 Too many open files
오류를 방지하기 위해 더 이상 사용되지 않을 때 fclose
사용하여 스트림을 fclose
합니다. 이는 런타임이 종료 될 때만 스트림이 닫히기 때문에 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 바이트를 읽은 다음 file.txt의 마지막 10 바이트를 읽습니다.
$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.'
}
재귀를 사용하여 디렉토리 복사
디렉토리를 복사하는 것은 디렉토리를 삭제하는 것과 거의 비슷하지만, unlink
가 아닌 파일 copy
가 사용된다는 점을 제외하면, 디렉토리의 경우 rmdir
대신 mkdir
이 사용됩니다. 처음에는 함수의 끝에 있어야합니다.
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
있습니다.
rename("~/file.txt", "~/file.html");
rename("~/dir", "~/old_dir");
rename("~/dir/file.txt", "~/dir2/file.txt");