PHP byDreamy postedSep 30, 2015

파일 데이터 저장하고 불러오기(파일 입출력)

?

단축키

Prev이전 문서

Next다음 문서

ESC닫기

+ - Up Down Comment Print

https://opentutorials.org/course/779/4929 



파일 열기

php의 파일관련 부분은 C언어와 매우 흡사하다. 간략하게 설명된 부분은 C언어의 서적을 참고하는 편이 더 좋을 것이다. 

fopen()

1
2
3
4
5
6
7
8
9
$DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT']
// 보통 수퍼글로벌 변수를 이런식으로 줄여 사용한다.
// DOCUMENT_ROOT는 웹 문서 트리의 루트를 가리킨다.
@ $fp = fopen("$DOCUMENT_ROOT/../orders/orders.txt",'ab'); // @fopen도 가능
if(!$fp) {
echo 'Could not processed!</body></html>';
exit;
}
  1. 첫 번째 파라미터는 파일의 경로 및 파일의 이름을 지정한다.
    orders.txt 파일은 일부러 배포할 목적의 파일이 아니라면 보안상의 이유로 웹에서 바로 접근할 수 없어야 한다. 웹 문서 트리의 루트의 부모 디렉터리(.. 부분)에 새로운 디렉터리를 만들어 사용한다.
  2. 두 번째 파라미터로 파일 모드를 지정한다. 보통 두 번째 파라미터까지만 입력한다.
    모드모드의미
    r읽기 모드읽기 전용. 처음에서 시작.
    r+읽기 모드읽고 쓰기. 처음에서 시작.
    w쓰기 모드쓰기 전용. 처음에서 시작. 기존 파일 삭제.
    w+쓰기 모드읽고 쓰기. 처음에서 시작. 기존 파일 삭제.
    x경고 쓰기쓰기 전용. 처음에서 시작. 기존 파일이 존재하면 false 반환하고 경고.
    x+경고 쓰기읽고 쓰기. 처음에서 시작. 기존 파일이 존재하면 false 반환하고 경고.
    a추가 모드쓰기 전용. 기존 파일의 끝에서 시작.
    a+추가 모드읽고 쓰기. 기존 파일의 끝에서 시작.
    b바이너리 모드다른 모드와 합쳐 사용. 바이너리와 텍스트 파일을 구별하는 경우에만 사용할 수 있다. 윈도우즈에서는 구별하며 유닉스에서는 구별하지 않는다. 이동성을 높이기 위해 항상 이 모드를 사용하는 것이 좋다. 바이너리 모드가 기본값이다.
    t텍스트 모드다른 모드와 합쳐 사용. 이 모드는 윈도우즈 시스템에서만 사용할 수 있다. 코드를 b 옵션으로 사용하도록 바꾸고 난 뒤가 아니라면 t 옵션은 사용하지 않는 편이 좋다.
  3. 세 번째 파라미터부터는 추가 인자로 꼭 넣어줄 필요가 있을 때에만 사용한다. 세 번째 파라미터는 include_path에서 파일을 찾을 때 사용한다.(그에 맞게 PHP 설정을 해야한다. 부록 A 참조) 이 옵션을 사용하면 디렉토리 이름이나 경로를 지정할 필요가 없다.
    1
    $fp = fopen('orders.txt', 'ab', true);
  4. 네 번째 파라미터는 프로토콜(http://와 같은)에 의해 정해진 파일 이름이나 외부에서 알려진 파일 이름을 사용할 수 있는데, 이에 대한 설명은 일단 생략한다.
php.ini 파일에서 allow_url_fopen을 활성시키면, fopen()에서 FTP나 HTTP를 사용해서 다른 곳에 있는 파일을 열 수 있다.
파일을 열 때 항상 권한 설정을 잘 해 주어야 한다.
대부분 시스템에서 스크립트는 웹 서버 사용자 권한으로 동작한다. 스크립트가 유닉스 시스템의
~/public_html/chapter2/ 디렉터리에 있다고 가정하고 스크립트가 쓸 수 있는 디렉터리를 만들어보자.
1
2
mkdir ~/orders
chmod 777 ~/orders
하지만 모든 사람이 쓸 수 있는 디렉터리는 보안상 상당히 위험하다. 그렇기 때문에 orders 디렉터리는 public_html 디렉터리의 부모에서 만들었다.(자세한 내용은 15장 전자상거래 보안 이슈)

 

 파일 쓰기

1
2
3
4
5
6
7
8
// fwrite(), fputs()는 동일
fwrite($fp, $outputstring[, strlen($outputstring)]);
int fwrite(resource handle, string string[, length])
// length는 파일에 쓸 최대 문자수
int file_put_contents(string filename, string data[, int flags[, resource context])
// string file_get_contents(string filename)와 쌍을 이룬다.(아래 파일 읽기에서 설명)
// fopen, fclose 불필요. resource는 20장 네트워크와 프로토콜 함수에서
fwrite에서 바이너리 모드를 써서 여러 플랫폼에서 사용할 수 있는 코드를 만들 때에는 세 번째 파라미터를 사용하는 것이 좋다. 
$outputstring을 저장할 때 각 필드는 \t, 각 레코드는 \n 등으로 구분 문자를 넣어주면 나중에 불러올 때 편리하다. 

 

 파일 닫기

1
2
fclose($fp);
// 성공시 true, 아니면 false 리턴

 

파일 읽기

파일의 끝 : feof()

1
2
3
while(!feof($fp)) {
// file read logic
}

 

한 줄씩 읽기 : fgets(), fgetss(), fgetcsv()

fgets() : 한 줄씩 읽는다. 가장 기본

1
2
3
4
$order = fgets($fp[, 999]);
// 읽는 최대 길이 999-1=998 바이트
// 파일에서 한 줄씩 읽는다.
// EOF를 만나거나 998바이트를 읽을 때까지 진행

fgetss() : 태그 제거

1
2
3
string fgetss(resource fp, int length[, string allowable_tags])
// 읽어 드린 문자열에서 PHP와 HTML 태그를 모두 제거
// 특정 태그를 남겨두고 싶으면 allowable_tags에 입력('<strong><br>'처럼)

fgetcsv() : 구분 문자로 나눠 배열에 저장

1
2
3
4
5
6
array fgetcsv(resource fp, int length[, string delimiter[, string enclosure]])
$order = fgetcsv($fp, 100, "\t");
// 구분 문자로 나누어서 배열에 저장한다.
// length : 읽으려는 한 줄의 길이보다 좀 더 길게 설정
// enclosure : 필드를 둘러싸는 문자를 지정하는 방식으로 설정하지 않는다면
// 기본적으로는 각각의 데이터 값을 ""로 둘러싸도록 한다.

 

파일 전체 읽기 : readfile(), fpassthru(), file(), file_get_contents()

readfile() : int 형. 바로 출력

1
2
3
4
5
6
int readfile(string filename[, int use_include_path[, resource context]])
readfile("$DOCUMENT_ROOT/../orders/orders.txt");
// 호출하면 알아서 파일을 열고 알아서 브라우저 출력을하고 알아서 파일을 닫는다.
// 두 번째 파라미터는 path추가. fopen에서 설명했음.
// 세 번째 파라미터는 http 등을 이용해 외부에서 열었을 경우에만 사용(20장)
// return 값은 파일에서 읽은 총 바이트 수

fpassthru() : boolean 형. 바로 출력

1
2
3
4
$fp = fopen("$DOCUMENT_ROOT/../order/orders.txt", 'rb');
fpassthru($fp);
// 포인터의 위치에서 파일 끝까지 읽어 표준 출력하고 알아서 파일을 닫는다.
// return 값으로 파일을 읽었으면 true, 아니면 false

file() : array 형. 변수 저장

1
2
3
4
$filearray = file("$DOCUMENT_ROOT/../orders/orders.txt");
// readfile()과 거의 동일
// 출력은 하지 않고 배열에 저장한다.
// 한 줄 한 줄이 배열의 한 요소가 된다.

file_get_contents() : string 형. 변수 저장

1
2
3
string file_get_contents(string filename)
// readfile()과 거의 동일
// 문자열로 리턴한다.

 

한 글자씩 읽기 : fgetc()

1
2
3
4
5
6
7
8
9
while(!feof($fp)) {
$char = fgetc($fp);
if(!feof($fp)) { // #2
echo ($char=="\n" ? "<br />" : $char); // #1
}
}
// #1 줄바꿈 문자를 <br />로 변환
// fgetc()를 사용하면 파일의 끝에서 EOF를 리턴받기 때문에
// 브라우저에서 EOF를 출력하지 않기 위해 #2에서 feof()를 다시 검사함.

느리기 때문에 사용하지 않는 편이 낫다.

 

임의의 길이 읽기 : fread()

1
string fread(resource fp, int length)

파일의 끝에 닿았거나 length만큼의 바이트를 읽었을 경우 값을 리턴한다.

 

기타 유용한 파일 함수

file_exists() : 파일 존재 여부

1
2
3
4
5
6
if(file_exists("$DOCUMENT_ROOT/../orders/orders.txt")) {
// process logic
}
else {
// not process logic
}

filesize() : 파일의 크기

1
2
3
4
5
6
echo filesize("$DOCUMENT_ROOT/../orders/orders.txt");
// 이 함수를 이용하여 fread()의 length로 주면 한번에 파일 전체를 읽을 수 있다.
$fp = fopen("$DOCUMENT_ROOT/../orders/orders.txt", 'rb');
echo nl2br(fread($fp, filesize("$DOCUMENT_ROOT/../orders/orders.txt")));
fclose($fp);
nl2br 함수는 '\n'을 <br />로 바꾸어 주는 PHP 함수이다.

unlink() : 파일 지우기

1
2
unlink("$DOCUMENT_ROOT/../orders/orders.txt");
// 실패시 false 리턴(권한이 없거나 파일이 없는 경우 등)

 

파일 내부 탐색하기 : rewind(), ftell(), fseek()

C언어에서 파일포인터의 위치를 조작할 수 있는 것처럼 php에서도 함수를 이용하여 파일포인터를 조작할 수 있다.
하지만 php에서 이 정도의 복잡한 작업이 필요한 경우라면 보통 데이터베이스를 이용하는 편이 나을 것이다.

  • rewind() : 파일 포인터를 시작으로 옮긴다.
  • ftell() : 현재 파일 포인터의 위치를 바이트 값으로 나타낸다.
  • fseek() : 파일 포인터를 파일의 다른 위치로 옮긴다. 

fseek()

1
int fseek(resource fp, int offset[, int whence])

whence에서부터 offset만큼 떨어진 곳에 파일 포인터 fp를 옮겨 놓는다.

whence의 값으로 가능한 값은 다음과 같다.(PHP 4부터 지원)

  • SEEK_SET : 파일의 처음
  • SEEK_CUR : 현재 위치
  • SEEK_END : 파일의 끝

 

파일에 락 걸기

1
2
boolean flock(resource fp, int operation[, int &wouldblock])
// wouldblock : 락을 얻는 과정에서 현재 프로세스가 멈출 수도 있는지
operation의미
LOCK_SH (1)읽기 락. 파일 공유 가능.
LOCK_EX (2)쓰기 락. 파일 공유 불가능.
LOCK_UN (3)락 해제.
LOCK_NB (4)락을 걸기 위해 스크립트가 정지하는 것을 막는다.

락을 사용하려면 모든 스크립트에서 flock을 사용해야 한다. 그렇지 않으면 큰 의미가 없어진다.

NFS나 다른 네트워크 파일 시스템 또는 FAT과 같이 오래된 파일 시스템에서는 사용할 수 없다.
다중 쓰레드 서버 API를 사용하고 있다면 제대로 동작하지 않을 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
// 쓰기 과정
$fp = fopen("$DOCUMENT_ROOT/../orders/orders.txt", 'ab');
flock($fp, LOCK_EX); // 쓰기 락
fwrite($fp, $outputstring);
flock($fp, LOCK_UN); // 락 해제
fclose($fp);
// 읽기 과정
$fp = fopen("$DOCUMENT_ROOT/../orders/orders.txt", 'r');
flock($fp, LOCK_SH); // 읽기 락
// 파일에서 읽는다.
flock($fp, LOCK_UN); // 락 해제
fclose($fp);

나눔글꼴 설치 안내


이 PC에는 나눔글꼴이 설치되어 있지 않습니다.

이 사이트를 나눔글꼴로 보기 위해서는
나눔글꼴을 설치해야 합니다.

설치 취소

Designed by sketchbooks.co.kr / sketchbook5 board skin

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5