php에서 2G이상의 파일을 다룰 수 있나요?

unicozy의 이미지

제가 하고자 하는 일은 파일의 특정 부분을 읽어서 웹으로 뿌려주는 것입니다. 2G이상의 파일을 다룰 수 있어야 하는데 여기서 막히고 있습니다.

http://kr.php.net/manual/kr/ref.filesystem.php을 참고해보면

Quote:
리눅스에서 PHP가 LFS(large files)를 지원하려면, 최근의 glibc를 사용하고, PHP에 다음 플래그를 지정하여 컴파일해야 합니다: -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64

라고 있어서 그렇게 했습니다. (데비안 소스패키지를 수정하려고 했는데 debian/rules를 돌리면 에러나 나서 포기하고 일단 tar 받아서 컴파일 했습니다.)

위옵션을 주고 컴파일을 했더니 2G이상의 파일도 fopen이 정상적으로 되더군요. 그런데 문제는

http://kr.php.net/manual/kr/language.types.integer.php

Quote:
약 20억을 최대값(부호가 있는 32비트)으로 사용할수 있을지라도, 정수의 크기는 플랫폼에 따라 달라지게 된다. PHP는 부호없는(unsigned) 정수 를 지원하지 않는다.

여기에 있었습니다. LFS를 지원하도록 컴파일을 해도 fseek로 넘기는 값이 20억을 넘어가면 이상한 곳을 읽더군요.
(file의 offset계산을 위해서는 BCMath를 사용했습니다. bcadd의 결과는 string으로 나옵니다.)

아무리 BCMath를 통해서 20억 이상의 offset을 계산하더라도 fseek가 offset을 integer로 변환하는 과정에서 원하는 결과를 얻지 못하는 것 같습니다.

구글링을 통해서 검색해본 결과 popen과 tail --bytes등을 통해서 쓰는 사람도 있는데, 그러면 속도가 느려질테고..(속도가 중요합니다 ㅜ.ㅜ)

정리하면,
php에서 2G 이상의 파일을 다루려면 어찌 해야 하나요?

송효진의 이미지

http://kr.php.net/manual/kr/function.fseek.php

해보진 않았지만 이렇게 하면 어떨까요?

fseek($fp, 1000000);
fseek($fp, 300, SEEK_CUR);
dragonkun의 이미지

fseek 사용할때..
SEEK_END로부터 거꾸로(음수로).. 접근해 보셨나요?

Emerging the World!

unicozy의 이미지

dragonkun wrote:
fseek 사용할때..
SEEK_END로부터 거꾸로(음수로).. 접근해 보셨나요?

다뤄야 할 파일이 테라 단위까지 올라가기때문에 SEEK_END로는 완벽하게 원하는 결과를 가져올 수 없었습니다.

송효진 wrote:
http://kr.php.net/manual/kr/function.fseek.php

해보진 않았지만 이렇게 하면 어떨까요?

fseek($fp, 1000000);
fseek($fp, 300, SEEK_CUR);

송효진님의 글을 보는순간 뒤통수를 맞은 것 같은 느낌이었어요 ^^
감사합니다. 위의 방법으로 성공했습니다.

소스가 회사 개발서버에 있는 관계로 월요일 출근하면 fseek wrapper 함수 코드를 올리도록 하겠습니다.

unicozy의 이미지

2G이상의 파일을 다루기 위한 fseek64 wrapper 함수입니다.

    - php에서 2G이상의 파일을 열 수 있도록 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
    옵션을 줘서 컴파일 해야 합니다.
    - php의 BCMath관련 함수를 사용하기 때문에 php컴파일시 --enable-bcmath 옵션을 줘서 컴파일 해야 합니다.

function fseek64($fp, $offset)
{
	$limit = "2000000000";
	if(bccomp($offset, $limit) == -1) {
		fseek($fp, $offset);
	}
	else {
		$lc = 0;
		fseek($fp, 0);
		$lc = bcdiv($offset, $limit);
		$offset = bcmod($offset, $limit);
		
		for($i=0; $i<$lc; $i++) {
			fseek($fp, $limit, SEEK_CUR);
		}
		fseek($fp, $offset, SEEK_CUR);
	}
}
[/]

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.