Reputation: 147
I'm trying to use PDFBox to get text from a PDF but I'm running into an exception. Here's the code I'm using to do the text stripping.
try
{
PDDocument document = PDDocument.load(decodedPdfDocument.getBytes());
PDFTextStripper Tstripper = new PDFTextStripper();
String st = Tstripper.getText(document);
System.out.println("Text:" + st);
}
catch (Exception e)
{
e.printStackTrace();
}
And here's the exception I'm getting.
java.io.IOException: java.util.zip.DataFormatException: invalid block type
at org.apache.pdfbox.filter.FlateFilter.decode(FlateFilter.java:83)
at org.apache.pdfbox.cos.COSInputStream.create(COSInputStream.java:69)
at org.apache.pdfbox.cos.COSStream.createInputStream(COSStream.java:167)
at org.apache.pdfbox.pdmodel.PDPage.getContents(PDPage.java:155)
at org.apache.pdfbox.pdfparser.PDFStreamParser.<init>(PDFStreamParser.java:91)
at org.apache.pdfbox.contentstream.PDFStreamEngine.processStreamOperators(PDFStreamEngine.java:485)
at org.apache.pdfbox.contentstream.PDFStreamEngine.processStream(PDFStreamEngine.java:469)
at org.apache.pdfbox.contentstream.PDFStreamEngine.processPage(PDFStreamEngine.java:150)
at org.apache.pdfbox.text.LegacyPDFStreamEngine.processPage(LegacyPDFStreamEngine.java:139)
at org.apache.pdfbox.text.PDFTextStripper.processPage(PDFTextStripper.java:391)
at org.apache.pdfbox.text.PDFTextStripper.processPages(PDFTextStripper.java:319)
at org.apache.pdfbox.text.PDFTextStripper.writeText(PDFTextStripper.java:266)
at org.apache.pdfbox.text.PDFTextStripper.getText(PDFTextStripper.java:227)
at com.cerner.fsi.testing.xds.provideandregister.ClinicalEventInErrorTest.testProvideAndRegisterCDAWrappedDocument_ClinicalEventInError(ClinicalEventInErrorTest.java:117)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at com.cerner.fsi.testing.xds.EnterpriseClientSpringJUnit4ClassRunner$1$1.run(EnterpriseClientSpringJUnit4ClassRunner.java:50)
at com.cerner.fsi.testing.xds.EnterpriseClientSpringJUnit4ClassRunner$1$1.run(EnterpriseClientSpringJUnit4ClassRunner.java:1)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:356)
at com.cerner.fsi.testing.xds.EnterpriseClientSpringJUnit4ClassRunner$1.evaluate(EnterpriseClientSpringJUnit4ClassRunner.java:43)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.util.zip.DataFormatException: invalid block type
at java.util.zip.Inflater.inflateBytes(Native Method)
at java.util.zip.Inflater.inflate(Inflater.java:259)
at java.util.zip.Inflater.inflate(Inflater.java:280)
at org.apache.pdfbox.filter.FlateFilter.decompress(FlateFilter.java:108)
at org.apache.pdfbox.filter.FlateFilter.decode(FlateFilter.java:74)
... 49 more
I've ran the PDF through validation and it's a valid 1.4 PDF. I'm also able to extract text using both Foxit and Acrobat frontend tools. Not quite sure what I'm doing wrong here, this is my first time using this API.
Upvotes: 0
Views: 5663
Reputation: 95928
According to a comment of the OP
The
decodedPdfDocument
comes from decoding a Base64 string. I'm creating a new string usingnew String(Base64.decode(documentString), "UTF-8");
This is the error. Never ever treat binary contents (like PDFs) as text! Instead let the decoded PDF document remain a byte[]
:
documentString = [...your base64 encoded PDF ...];
byte[] decodedPdfDocument = Base64.decode(documentString);
...
PDDocument document = PDDocument.load(decodedPdfDocument);
PDFTextStripper textStripper = new PDFTextStripper();
String st = textStripper.getText(document);
As a background: When you do something like
String string = new String(bytes, encoding);
for a byte[] bytes
, your bytes
are decoded assuming they contain text encoded to bytes using encoding
.
If your bytes
are not text encoded using encoding
, this process can be destructive, byte sequences that don't make sense according to the assumed encoding will be converted to a replacement character in the String
. When you later retrieve bytes from the String using getBytes()
, you'll retrieve representations of the replacement character instead of the original byte sequences.
Upvotes: 4