그럼 이전 글에 이어서 계속 진행하겠습니다.
pdf2text($filename) 을 하다가 마쳤었는데요.
이어서 알아볼 것은 preg_match_all 함수입니다.
preg_match_all("#obj(.*)endobj#ismU", $infile, $objects);
이런 초반부터 어려운게 걸렸네요.
이 함수에는 3개의 파라미터가 들어가는데요.
첫번쨰 파라미터는 정규표현식이 들어갑니다.
이 첫번째 파라미터의 패턴을 가지고 두번쨰 파라미터에 있는 객체내를 search 하는 겁니다.
그래서 그 정규식대로 구분해서 세번째 파라미터에 있는 변수에 결과를 담는거죠.
이 정규식과 관련해서는 여기와 여기 에 있는 글들을 참조하세요.
그리고 PHP 튜토리얼 사이트는 여기와 여기 가 있습니다.
이 preg_match_all 메소드에 대한 튜토리얼은 여기에 있습니다.
예제를 하나 보시면...
<?php
preg_match_all("|<[^>]+>(.*)</[^>]+>|U",
"<b>example: </b><div align=left>this is a test</div>",
$out, PREG_PATTERN_ORDER);
echo $out[0][0] . ", " . $out[0][1] . "\n";
echo $out[1][0] . ", " . $out[1][1] . "\n";
?>
위 코드를 실행하면 아래와 같은 결과를 얻습니다.
<b>example: </b>, <div align=left>this is a test</div> example: , this is a test
그러니까 첫번째 파라미터로 들어간 정규식은 모든 태그를 없애는 거나보네요.
그래서 결과가 배열 변수 $out 에 들어가게 되는데요.
이 배열의 첫번째 열에는 full pattern 이 들어가고 두번쨰 열이 바로 이 태그가 없어진 값들이 들어갑니다.
정규식을 잘 몰라서 왜 그런지는 모르겠구요.
하여간 우리가 공부하는 소스코드는 PDF 의 내용을 담은 변수를 #obj(.*)endobj#ismU 라는 정규식을 써서 Search하고 그 값이 $objects 에 들어갑니다.
참고로 pdf 파일은 수많은 obj/endobj, stream/endstream , Startxref/Xref,Trailer 등으로 구성 돼 있습니다.
위와 같은 PDF 파일이 있다면 바이너리 파일은 아래와 같습니다.
%PDF-1.7 1 0 obj % entry point << /Type /Catalog /Pages 2 0 R >> endobj 2 0 obj << /Type /Pages /MediaBox [ 0 0 200 200 ] /Count 1 /Kids [ 3 0 R ] >> endobj 3 0 obj << /Type /Page /Parent 2 0 R /Resources << /Font << /F1 4 0 R >> >> /Contents 5 0 R >> endobj 4 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Times-Roman >> endobj 5 0 obj % page content << /Length 44 >> stream BT 70 50 TD /F1 12 Tf (Hello, world!) Tj ET endstream endobj xref 0 6 0000000000 65535 f 0000000010 00000 n 0000000079 00000 n 0000000173 00000 n 0000000301 00000 n 0000000380 00000 n trailer << /Size 6 /Root 1 0 R >> startxref 492 %%EOF
자세한 내용을 알고 싶으시면 여기 를 참조하세요.
이 프로그램 하나 이해하기 위해 공부해야 할 것들이 무지 많군요.
|
|
원래 소스로 돌아가서요.
for ($i = 0; $i < count($objects); $i++) {
$currentObject = $objects[$i];
if (preg_match("#stream(.*)endstream#ismU", $currentObject, $stream)) {
$stream = ltrim($stream[1]);
$options = getObjectOptions($currentObject);
if (!(empty($options["Length1"]) && empty($options["Type"]) && empty($options["Subtype"])))
continue;
$data = getDecodedStream($stream, $options);
if (strlen($data)) {
if (preg_match_all("#BT(.*)ET#ismU", $data, $textContainers)) {
$textContainers = @$textContainers[1];
getDirtyTexts($texts, $textContainers);
} else
getCharTransformations($transformations, $data);
}
}
}
아까 얻었던 $objects 배열의 count 만큼 for 문을 돌립니다.
바이너리 파일을 하나하나 텍스트 문자로 변환시키기 위해 전체 $objects 를 for 문 돌리는 거겠죠.
이 for 문 안에서는 $objects 배열에 있는 각각의 객체들을 일단 $currentObject 에 담네요.
그 다음에 다시 PCRE 함수가 나왔네요.
이와 관련해서는 저 위에 튜토리얼 페이지 링크를 걸어놨죠?
if 문안에 preg_match("#stream(.*)endstream#ismU", $currentObject, $stream) 이 있습니다.
위 정규식으로 search 한 내용을 $stream 에 담슴니다.
한개의 stream 을 담는거네요.
PDF 소개글을 보면 Stream 은 아래와 같이 정의 돼 있습니다.
Stream
(<< /Length ... >> stream ... endstream): embedded data, can
be compressed. It starts with a dictionary that describes the stream
such as its length or the encoding (/Filter
) is uses.
stream 에 대해 자세히 공부하시려면 여기 로 가세요.
그 다음은 php2text.php 에 있는 getObjectOptions($currentObject)를 콜 합니다.
흠.... 소스를 자세히 뜯어 보니까 그 흐름은 좀 더 이해하게 되는데요...
이 소스를 완벽하게 이해하고 또 마음대로 수정해서 사용하려면
PHP 정규 표현식 (regular expressions) 를 알아야 하고 PCRE 함수를 알아야 하고 PDF 의 구조를 알아야 하네요.
일단 오늘의 성과는 이 소스를 이해하기 위해 필요한 지식 중 내가 뭐가 부족한지 알았습니다.
시간이 되면 파고 들겠는데... 그럴 시간이 있을 지 모르겠네요.
일단 오늘은 여기까지 하구요. 다음 글에서는 getObjectOptions() 메소드를 공부할 생각입니다.
그럼...
'etc. > PHP' 카테고리의 다른 글
PDF 내용을 Text 로 추출하는 PHP 프로그램 분석해 보기 7 (0) | 2013.01.16 |
---|---|
PDF 내용을 Text 로 추출하는 PHP 프로그램 분석해 보기 6 (0) | 2013.01.16 |
PDF 내용을 Text 로 추출하는 PHP 프로그램 분석해 보기 5 (0) | 2013.01.15 |
PDF 내용을 Text 로 추출하는 PHP 프로그램 분석해 보기 4 (0) | 2013.01.08 |
PDF 내용을 Text 로 추출하는 PHP 프로그램 분석해 보기 3 (0) | 2013.01.08 |
PDF 내용을 Text 로 추출하는 PHP 프로그램 분석해 보기 1 (0) | 2013.01.05 |
PHP와 XSL 로 XML 변환하기 (0) | 2012.12.21 |
PHP로 XML , JSON 다루기 (2) | 2012.08.24 |
-PHP - Proxy 통해 원격 파일 존재 여부 파악하기 (0) | 2012.07.19 |