브루노 (Bruno)는 문제를 설명하고 문제를 해결하는 방법을 잘 설명했지만 프로그래밍에 익숙하지 않고 새로운 것을 익혔다 고 말하면서 posted a very similar and related question 조금만 더 자세히 설명 드리겠습니다.
- :
- 는
- 각 PDF 그런 다음 단일 페이지
목적이 PDF 파일의 전체 디렉토리있다 :
첫째, 과학적 이해를 적어 보자 각 PDF의 텍스트를 추출하십시오
- 예전과 비교하십시오 패턴으로 tracted 텍스트 중 하나
- 다음 파일 이름을 경기를 할 사용하여 일치가 있다면
: 파일이
- 에 원본 PDF를 추가 존재하는 경우
- 일치가없는 경우 의 PDF
계속하기 전에 알아야 할 몇 가지가있다하여 새 파일을 만듭니다. FileMode.OpenOrCreate
을 사용하여 "추가 모드"에서 작업하려고했습니다. 그것은 좋은 추측 이었지만 부정확했습니다. PDF 형식에는 시작과 끝이 모두 있으므로 "여기에서 시작"과 "끝내기"가 있습니다. 기존 파일에 다른 PDF (또는 해당 내용)를 추가하려고하면 "여기에 끝"부분을 지나서 작성하는 것입니다. 기껏해야 정크 데이터가 무시되지만 더 많은 PDF가 손상 될 가능성이 높습니다. 거의 모든 파일 형식에서도 마찬가지입니다. XML 문서에는 하나의 루트 요소 만 있기 때문에 연결된 두 개의 XML 파일은 유효하지 않습니다.
둘째로 관련되었지만 iText/iTextSharp는 기존 파일을 편집 할 수 없습니다. 이건 매우 중요합니다. 그러나 다른 파일의 정확한 또는 수정 된 버전을 사용하는 새로운 파일을 만들 수 있습니다. 나는 이것이 얼마나 중요한지 강조 할 수 있는지 모르겠다.
셋째, 반복적으로 복사되는 줄을 사용하고 있지만 매우 잘못되어 실제로 데이터가 손상 될 수 있습니다. 그것이 왜 나쁜지에 대해서는 read this입니다.
currentText = Encoding.UTF8.GetString(Encoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(currentText)));
넷째, 검색을 수행하는 데 지나치게 복잡한 방법 인 RegEx를 사용하고 있습니다. 어쩌면 당신이 게시 한 코드는 단지 예제 일 뿐이지 만, 그렇지 않다면 currentText.Contains("")
을 사용하거나, 아니면 currentText.IndexOf("", StringComparison.InvariantCultureIgnoreCase)
을 무시할 필요가 있다면 추천 할 것입니다. 의심스러운 점을 위해 아래 코드에서는 RegEx가 더 복잡한 것으로 가정합니다.
아래 내용은 모든 것을 처리해야하는 완전한 작동 예제입니다. PDF에 액세스 할 수 없으므로 두 번째 섹션에서는 실제로 검색 용어가 추가 된 100 개의 샘플 PDF를 만듭니다. 귀하의 실제 코드는 분명히 그렇게하지 않을 것이지만 우리는 당신과 함께 일하는 공통점을 필요로합니다. 세 번째 섹션은 수행하려는 검색 및 병합 기능입니다. 바라건대 코드의 주석은 모든 것을 설명하기를 바랍니다.
/**
* Step 1 - Variable Setup
*/
//This is the folder that we'll be basing all other directory paths on
var workingFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
//This folder will hold our PDFs with text that we're searching for
var folderPathContainingPdfsToSearch = Path.Combine(workingFolder, "Pdfs");
var folderPathContainingPdfsCombined = Path.Combine(workingFolder, "Pdfs Combined");
//Create our directories if they don't already exist
System.IO.Directory.CreateDirectory(folderPathContainingPdfsToSearch);
System.IO.Directory.CreateDirectory(folderPathContainingPdfsCombined);
var searchText1 = "ABC";
var searchText2 = "DEF";
/**
* Step 2 - Create sample PDFs
*/
//Create 100 sample PDFs
for (var i = 0; i < 100; i++) {
using (var fs = new FileStream(Path.Combine(folderPathContainingPdfsToSearch, i.ToString() + ".pdf"), FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
//Add a title so we know what page we're on when we combine
doc.Add(new Paragraph(String.Format("This is page {0}", i)));
//Add various strings every once in a while.
//(Yes, I know this isn't evenly distributed but I haven't
// had enough coffee yet.)
if (i % 10 == 3) {
doc.Add(new Paragraph(searchText1));
} else if (i % 10 == 6) {
doc.Add(new Paragraph(searchText2));
} else if (i % 10 == 9) {
doc.Add(new Paragraph(searchText1 + searchText2));
} else {
doc.Add(new Paragraph("Blah blah blah"));
}
doc.Close();
}
}
}
}
/**
* Step 3 - Search and merge
*/
//We'll search for two different strings just to add some spice
var reg = new Regex("(" + searchText1 + "|" + searchText2 + ")");
//Loop through each file in the directory
foreach (var filePath in Directory.EnumerateFiles(folderPathContainingPdfsToSearch, "*.pdf")) {
using (var pdfReader = new PdfReader(filePath)) {
for (var page = 1; page <= pdfReader.NumberOfPages; page++) {
//Get the text from the page
var currentText = PdfTextExtractor.GetTextFromPage(pdfReader, page, new SimpleTextExtractionStrategy());
currentText.IndexOf("", StringComparison.InvariantCultureIgnoreCase)
//DO NOT DO THIS EVER!! See this for why https://stackoverflow.com/a/10191879/231316
//currentText = Encoding.UTF8.GetString(Encoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(currentText)));
//Match our pattern against the extracted text
var matches = reg.Matches(currentText);
//Bail early if we can
if (matches.Count == 0) {
continue;
}
//Loop through each match
foreach (var m in matches) {
//This is the file path that we want to target
var destFile = Path.Combine(folderPathContainingPdfsCombined, m.ToString() + ".pdf");
//If the file doesn't already exist then just copy the file and move on
if (!File.Exists(destFile)) {
System.IO.File.Copy(filePath, destFile);
continue;
}
//The file exists so we're going to "append" the page
//However, writing to the end of file in Append mode doesn't work,
//that would be like "add a file to a zip" by concatenating two
//two files. In this case, we're actually creating a brand new file
//that "happens" to contain the original file and the matched file.
//Instead of writing to disk for this new file we're going to keep it
//in memory, delete the original file and write our new file
//back onto the old file
using (var ms = new MemoryStream()) {
//Use a wrapper helper provided by iText
var cc = new PdfConcatenate(ms);
//Open for writing
cc.Open();
//Import the existing file
using (var subReader = new PdfReader(destFile)) {
cc.AddPages(subReader);
}
//Import the matched file
//The OP stated a guarantee of only 1 page so we don't
//have to mess around with specify which page to import.
//Also, PdfConcatenate closes the supplied PdfReader so
//just use the variable pdfReader.
using (var subReader = new PdfReader(filePath)) {
cc.AddPages(subReader);
}
//Close for writing
cc.Close();
//Erase our exisiting file
File.Delete(destFile);
//Write our new file
File.WriteAllBytes(destFile, ms.ToArray());
}
}
}
}
}
파일을 계속 덮어 쓰는 것처럼 보입니다. 바깥 쪽 루프에'PdfCopy' 인스턴스를 생성해야합니다. 사실, 당신의 코드를 이해하지 못합니다. 당신이 원하는 것과 일치하지 않는 것 같습니다. 코드를 문서화 할 수 있습니까 (예 : 원하는 것을 설명하는 설명을 추가하여)? –
당신은 PdfCopy, PdfReader, Document를 의미합니까? 이 시점에서 PdfReader가 필요합니까? 최종 문서에서 두 번째, 세 번째 등의 페이지로 파일 (정규식 일치가 있음)을 추가하려고합니다. –
내 목표는 최종 문서에 페이지를 추가하는 대신에 –