Я думаю, что ваш единственный вариант использования iText - это разобрать маркеры PDF вручную. До этого я бы have a copy of the PDF spec handy.
(я парень .Net, поэтому я использую iTextSharp, но кроме некоторых отличий капитализации и деклараций собственности они почти 100% то же самое.)
Вы можете получить индивидуальные жетоны с помощью PRTokeniser
объект, в который вы подаете байты, от вызова getPageContent(pageNum)
на PdfReader
.
//Get bytes for page 1
byte[] pageBytes = reader.getPageContent(1);
//Get the tokens for page 1
PRTokeniser tokeniser = new PRTokeniser(pageBytes);
Тогда просто цикл через PRTokeniser
:
PRTokeniser.TokType tokenType;
string tokenValue;
while (tokeniser.nextToken()) {
tokenType = tokeniser.tokenType;
tokenValue = tokeniser.stringValue;
//...check tokenValue, do something with it
}
Как далеко tokenValue
, вы хотели бы, вероятно, искать для re
и l
значения для прямоугольника и линии. Если вы видите re
, то вы хотите посмотреть на предыдущих 4 значений, и если вы видите l
то предыдущий 2 значения. Это также означает, что вам нужно хранить каждый tokenValue
в массиве, чтобы вы могли оглянуться назад.
В зависимости от того, что вы использовали для создания PDF-документа, вы можете получить интересные результаты. Например, я создал таблицу из 4 ячеек с Microsoft Word и сохранил ее как PDF. По некоторым причинам есть два набора из 10 прямоугольников со многими дубликатами, но общая идея все еще работает.
Ниже приведен код C#, предназначенный для iTextSharp 5.1.1.0. Вы должны иметь возможность конвертировать его в Java и iText очень легко, я отметил одну строку, которая имеет .Net-специфический код, который необходимо скопировать из общего списка (List<string>
) в эквивалент Java, возможно, ArrayList
. Вам также нужно будет отрегулировать некоторый корпус, .Net использует Object.Method()
, тогда как Java использует Object.method()
. Наконец, .Net обращается к свойствам без get и sets, поэтому Object.Property
- это как getter, так и setter по сравнению с Java Object.getProperty
и Object.setProperty
.
Надеюсь, это поможет вам начать хотя бы!
//Source file to read from
string sourceFile = "c:\\Hello.pdf";
//Bind a reader to our PDF
PdfReader reader = new PdfReader(sourceFile);
//Create our buffer for previous token values. For Java users, List<string> is a generic list, probably most similar to an ArrayList
List<string> buf = new List<string>();
//Get the raw bytes for the page
byte[] pageBytes = reader.GetPageContent(1);
//Get the raw tokens from the bytes
PRTokeniser tokeniser = new PRTokeniser(pageBytes);
//Create some variables to set later
PRTokeniser.TokType tokenType;
string tokenValue;
//Loop through each token
while (tokeniser.NextToken()) {
//Get the types and value
tokenType = tokeniser.TokenType;
tokenValue = tokeniser.StringValue;
//If the type is a numeric type
if (tokenType == PRTokeniser.TokType.NUMBER) {
//Store it in our buffer for later user
buf.Add(tokenValue);
//Otherwise we only care about raw commands which are categorized as "OTHER"
} else if (tokenType == PRTokeniser.TokType.OTHER) {
//Look for a rectangle token
if (tokenValue == "re") {
//Sanity check, make sure we have enough items in the buffer
if (buf.Count < 4) throw new Exception("Not enough elements in buffer for a rectangle");
//Read and convert the values
float x = float.Parse(buf[buf.Count - 4]);
float y = float.Parse(buf[buf.Count - 3]);
float w = float.Parse(buf[buf.Count - 2]);
float h = float.Parse(buf[buf.Count - 1]);
//..do something with them here
}
}
}
Ссылка на PDF Спецификация в ответе более не действительна. Вы можете попробовать этот URL. https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf – user1567291