> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/android/get-started/samples/textextracttest.md).

# TextExtract

Sample Java, Kotlin code for using Apryse Android SDK to read a PDF (parse and extract text).

Sample Java, Kotlin code for using Apryse Android SDK to read a PDF (parse and extract text). If you'd like to search text on PDF pages, see our code sample for [text search](/android/get-started/samples/textsearchtest.md).

Learn more about our full [PDF Data Extraction SDK Capabilities](https://apryse.com/capabilities/extraction).

To start your free trial, [get started with Android SDK](/android/get-started/get-started.md).

{% tabs %}
{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

package com.pdftron.android.pdfnetsdksamples.samples;

import com.pdftron.android.pdfnetsdksamples.OutputListener;
import com.pdftron.android.pdfnetsdksamples.PDFNetSample;
import com.pdftron.android.pdfnetsdksamples.R;
import com.pdftron.android.pdfnetsdksamples.util.Utils;
import com.pdftron.common.PDFNetException;
import com.pdftron.pdf.Element;
import com.pdftron.pdf.ElementReader;
import com.pdftron.pdf.PDFDoc;
import com.pdftron.pdf.Page;
import com.pdftron.pdf.PageIterator;
import com.pdftron.pdf.Rect;
import com.pdftron.pdf.TextExtractor;

import java.text.DecimalFormat;
import java.util.ArrayList;

public class TextExtractTest extends PDFNetSample {

	private static OutputListener mOutputListener;

	private static ArrayList<String> mFileList = new ArrayList<>();

    public TextExtractTest() {
        setTitle(R.string.sample_textextract_title);
        setDescription(R.string.sample_textextract_description);
    }

	@Override
	public void run(OutputListener outputListener) {
		super.run(outputListener);
		mOutputListener = outputListener;
		mFileList.clear();
		printHeader(outputListener);

        // string output_path = "../../TestFiles/Output/";
        boolean example1_basic = false;
        boolean example2_xml = false;
        boolean example3_wordlist = false;
        boolean example4_advanced = true;
        boolean example5_low_level = false;

        // Sample code showing how to use high-level text extraction APIs.
        try (PDFDoc doc = new PDFDoc(Utils.getAssetTempFile(INPUT_PATH + "newsletter.pdf").getAbsolutePath())) {
            doc.initSecurityHandler();

            Page page = doc.getPage(1);
            if (page == null) {
                mOutputListener.println("Page not found.");
            }

            TextExtractor txt = new TextExtractor();
            txt.begin(page);  // Read the page.
            // Other options you may want to consider...
            // txt.Begin(page, 0, TextExtractor.ProcessingFlags.e_no_dup_remove);
            // txt.Begin(page, 0, TextExtractor.ProcessingFlags.e_remove_hidden_text);
            // ...

            // Example 1. Get all text on the page in a single string.
            // Words will be separated with space or new line characters.
            if (example1_basic) {
                // Get the word count.
                mOutputListener.println("Word Count: " + txt.getWordCount());

                mOutputListener.println("\n\n- GetAsText --------------------------\n" + txt.getAsText());
                mOutputListener.println("-----------------------------------------------------------");
            }

            // Example 2. Get XML logical structure for the page.
            if (example2_xml) {
                String text = txt.getAsXML(TextExtractor.e_words_as_elements | TextExtractor.e_output_bbox | TextExtractor.e_output_style_info);
                mOutputListener.println("\n\n- GetAsXML  --------------------------\n" + text);
                mOutputListener.println("-----------------------------------------------------------");
            }

            // Example 3. Extract words one by one.
            if (example3_wordlist) {
                TextExtractor.Word word;
                for (TextExtractor.Line line = txt.getFirstLine(); line.isValid(); line = line.getNextLine()) {
                    for (word = line.getFirstWord(); word.isValid(); word = word.getNextWord()) {
                        mOutputListener.println(word.getString());
                    }
                }
                mOutputListener.println("-----------------------------------------------------------");
            }

            // Example 4. A more advanced text extraction example.
            // The output is XML structure containing paragraphs, lines, words,
            // as well as style and positioning information.
            if (example4_advanced) {
                Rect bbox;
                int cur_flow_id = -1, cur_para_id = -1;

                TextExtractor.Line line;
                TextExtractor.Word word;
                TextExtractor.Style s, line_style;

                mOutputListener.println("<PDFText>");
                // For each line on the page...
                for (line = txt.getFirstLine(); line.isValid(); line = line.getNextLine()) {
                    if (line.getNumWords() == 0)
                        continue;
                    if (cur_flow_id != line.getFlowID()) {
                        if (cur_flow_id != -1) {
                            if (cur_para_id != -1) {
                                cur_para_id = -1;
                                mOutputListener.println("</Para>");
                            }
                            mOutputListener.println("</Flow>");
                        }
                        cur_flow_id = line.getFlowID();
                        mOutputListener.println("<Flow id=\"" + cur_flow_id + "\">");
                    }

                    if (cur_para_id != line.getParagraphID()) {
                        if (cur_para_id != -1)
                            mOutputListener.println("</Para>");
                        cur_para_id = line.getParagraphID();
                        mOutputListener.println("<Para id=\"" + cur_para_id + "\">");
                    }

                    bbox = line.getBBox();
                    line_style = line.getStyle();
                    mOutputListener.print("<Line box=\"" +  String.format("%.2f, %.2f, %.2f, %.2f", bbox.getX1(), bbox.getY1(), bbox.getX2(), bbox.getY2()) + "\"");
                    printStyle(line_style);
                    mOutputListener.println(" cur_num=\"" + line.getCurrentNum() + "\">");
                 

                    // For each word in the line...
                    for (word = line.getFirstWord(); word.isValid(); word = word.getNextWord()) {
                        // Output the bounding box for the word.
                        bbox = word.getBBox();
                        mOutputListener.print("<Word box=\"" +  String.format("%.2f, %.2f, %.2f, %.2f", bbox.getX1(), bbox.getY1(), bbox.getX2(), bbox.getY2()) + "\"");
                        mOutputListener.print(" cur_num=\"" + word.getCurrentNum() + "\"");
                        int sz = word.getStringLen();
                        if (sz == 0) continue;

                        // If the word style is different from the parent style, output the new style.
                        s = word.getStyle();
                        if (!s.equals(line_style)) {
                            printStyle(s);
                        }

                        mOutputListener.print(">" + word.getString());
                        mOutputListener.println("</Word>");
                    }
                    mOutputListener.println("</Line>");
                }

                if (cur_flow_id != -1) {
                    if (cur_para_id != -1) {
                        cur_para_id = -1;
                        mOutputListener.println("</Para>");
                    }
                    mOutputListener.println("</Flow>");
                }
            }
            txt.destroy();
            mOutputListener.println("</PDFText>");
        } catch (PDFNetException e) {
            mOutputListener.printError(e.getStackTrace());
        }

        // Sample code showing how to use low-level text extraction APIs.
        if (example5_low_level) {
            try (PDFDoc doc = new PDFDoc((Utils.getAssetTempFile(INPUT_PATH + "newsletter.pdf").getAbsolutePath()))) {
                doc.initSecurityHandler();

                // Example 1. Extract all text content from the document

                ElementReader reader = new ElementReader();
                //  Read every page
                for (PageIterator itr = doc.getPageIterator(); itr.hasNext(); ) {
                    reader.begin(itr.next());
                    DumpAllText(reader);
                    reader.end();
                }

                // Example 2. Extract text content based on the
                // selection rectangle.
                mOutputListener.print("\n----------------------------------------------------");
                mOutputListener.print("\nExtract text based on the selection rectangle.");
                mOutputListener.println("\n----------------------------------------------------");

                Page first_page = doc.getPageIterator().next();
                String s1 = ReadTextFromRect(first_page, new Rect(27, 392, 563, 534), reader);
                mOutputListener.print("\nField 1: " + s1);

                s1 = ReadTextFromRect(first_page, new Rect(28, 551, 106, 623), reader);
                mOutputListener.print("\nField 2: " + s1);

                s1 = ReadTextFromRect(first_page, new Rect(208, 550, 387, 621), reader);
                mOutputListener.print("\nField 3: " + s1);

                // ...
                mOutputListener.println("Done.");
            } catch (Exception e) {
                mOutputListener.printError(e.getStackTrace());
            }
        }

		for (String file : mFileList) {
			addToFileList(file);
		}
		printFooter(outputListener);
	}


    static void printStyle(TextExtractor.Style s) {
        byte r = s.getColor()[0];
		byte g = s.getColor()[1];
		byte b = s.getColor()[2];
        String rgb_hex =  String.format("%02X%02X%02X;", r, g, b );
        DecimalFormat df = new DecimalFormat("#.#");
        mOutputListener.print(" style=\"font-family:" + s.getFontName() + "; "
                + "font-size:" + df.format(s.getFontSize()) + ";"
                + (s.isSerif() ? " sans-serif; " : " ")
                + "color:#" + rgb_hex + "\"");
    }

    // A utility method used to dump all text content in the console window.
    static void DumpAllText(ElementReader reader) throws PDFNetException {
        Element element;
        while ((element = reader.next()) != null) {
            switch (element.getType()) {
                case Element.e_text_begin:
                    mOutputListener.println("\n--> Text Block Begin");
                    break;
                case Element.e_text_end:
                    mOutputListener.println("\n--> Text Block End");
                    break;
                case Element.e_text: {
                    Rect bbox = element.getBBox();
                    if (bbox == null) continue;
                    mOutputListener.println("\n--> BBox: " + bbox.getX1() + ", "
                            + bbox.getY1() + ", "
                            + bbox.getX2() + ", "
                            + bbox.getY2());

                    String arr = element.getTextString();
                    mOutputListener.println(arr);
                }
                break;
                case Element.e_text_new_line:
                    mOutputListener.println("\n--> New Line");
                    break;
                case Element.e_form:                // Process form XObjects
                    reader.formBegin();
                    DumpAllText(reader);
                    reader.end();
                    break;
            }
        }
    }

    // A helper method for ReadTextFromRect
    static String RectTextSearch(ElementReader reader, Rect pos) throws PDFNetException {
        Element element;
        String srch_str = new String();
        while ((element = reader.next()) != null) {
            switch (element.getType()) {
                case Element.e_text: {
                    Rect bbox = element.getBBox();
                    if (bbox == null) continue;
                    if (bbox.intersectRect(bbox, pos)) {
                        String arr = element.getTextString();
                        srch_str += arr;
                        srch_str += "\n"; // add a new line?
                    }
                    break;
                }
                case Element.e_text_new_line: {
                    break;
                }
                case Element.e_form: // Process form XObjects
                {
                    reader.formBegin();
                    srch_str += RectTextSearch(reader, pos);
                    reader.end();
                    break;
                }
            }
        }
        return srch_str;
    }

    // A utility method used to extract all text content from
    // a given selection rectangle. The rectangle coordinates are
    // expressed in PDF user/page coordinate system.
    static String ReadTextFromRect(Page page, Rect pos, ElementReader reader) throws PDFNetException {
        reader.begin(page);
        String srch_str = RectTextSearch(reader, pos);
        reader.end();
        return srch_str;
    }

}
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

package com.pdftron.android.pdfnetsdksamples.samples

import com.pdftron.android.pdfnetsdksamples.OutputListener
import com.pdftron.android.pdfnetsdksamples.PDFNetSample
import com.pdftron.android.pdfnetsdksamples.R
import com.pdftron.android.pdfnetsdksamples.util.Utils
import com.pdftron.common.PDFNetException
import com.pdftron.pdf.*
import java.text.DecimalFormat
import java.util.*

class TextExtractTest : PDFNetSample() {
    init {
        setTitle(R.string.sample_textextract_title)
        setDescription(R.string.sample_textextract_description)
    }

    override fun run(outputListener: OutputListener?) {
        super.run(outputListener)
        mOutputListener = outputListener
        mFileList.clear()
        printHeader(outputListener!!)

        // string output_path = "../../TestFiles/Output/";
        val example1_basic = false
        val example2_xml = false
        val example3_wordlist = false
        val example4_advanced = true
        val example5_low_level = false

        // Sample code showing how to use high-level text extraction APIs.
        try {
            PDFDoc(Utils.getAssetTempFile(PDFNetSample.INPUT_PATH + "newsletter.pdf")!!.absolutePath).use { doc ->
                doc.initSecurityHandler()

                val page = doc.getPage(1)
                if (page == null) {
                    mOutputListener!!.println("Page not found.")
                }

                val txt = TextExtractor()
                txt.begin(page!!)  // Read the page.
                // Other options you may want to consider...
                // txt.Begin(page, 0, TextExtractor.ProcessingFlags.e_no_dup_remove);
                // txt.Begin(page, 0, TextExtractor.ProcessingFlags.e_remove_hidden_text);
                // ...

                // Example 1. Get all text on the page in a single string.
                // Words will be separated with space or new line characters.
                if (example1_basic) {
                    // Get the word count.
                    mOutputListener!!.println("Word Count: " + txt.wordCount)

                    mOutputListener!!.println("\n\n- GetAsText --------------------------\n" + txt.asText)
                    mOutputListener!!.println("-----------------------------------------------------------")
                }

                // Example 2. Get XML logical structure for the page.
                if (example2_xml) {
                    val text = txt.getAsXML(TextExtractor.e_words_as_elements or TextExtractor.e_output_bbox or TextExtractor.e_output_style_info)
                    mOutputListener!!.println("\n\n- GetAsXML  --------------------------\n$text")
                    mOutputListener!!.println("-----------------------------------------------------------")
                }

                // Example 3. Extract words one by one.
                if (example3_wordlist) {
                    var word: TextExtractor.Word
                    var line: TextExtractor.Line = txt.firstLine
                    while (line.isValid) {
                        word = line.firstWord
                        while (word.isValid) {
                            mOutputListener!!.println(word.string)
                            word = word.nextWord
                        }
                        line = line.nextLine
                    }
                    mOutputListener!!.println("-----------------------------------------------------------")
                }

                // Example 4. A more advanced text extraction example.
                // The output is XML structure containing paragraphs, lines, words,
                // as well as style and positioning information.
                if (example4_advanced) {
                    var bbox: Rect
                    var cur_flow_id = -1
                    var cur_para_id = -1

                    var line: TextExtractor.Line
                    var word: TextExtractor.Word
                    var s: TextExtractor.Style
                    var line_style: TextExtractor.Style

                    mOutputListener!!.println("<PDFText>")
                    // For each line on the page...
                    line = txt.firstLine
                    while (line.isValid) {
                        if (line.numWords == 0) {
                            line = line.nextLine
                            continue
                        }
                        if (cur_flow_id != line.flowID) {
                            if (cur_flow_id != -1) {
                                if (cur_para_id != -1) {
                                    cur_para_id = -1
                                    mOutputListener!!.println("</Para>")
                                }
                                mOutputListener!!.println("</Flow>")
                            }
                            cur_flow_id = line.flowID
                            mOutputListener!!.println("<Flow id=\"$cur_flow_id\">")
                        }

                        if (cur_para_id != line.paragraphID) {
                            if (cur_para_id != -1)
                                mOutputListener!!.println("</Para>")
                            cur_para_id = line.paragraphID
                            mOutputListener!!.println("<Para id=\"$cur_para_id\">")
                        }

                        bbox = line.bBox
                        line_style = line.style
                        mOutputListener!!.print("<Line box=\"" + String.format("%.2f, %.2f, %.2f, %.2f", bbox.x1, bbox.y1, bbox.x2, bbox.y2) + "\"")
                        printStyle(line_style)
                        mOutputListener!!.println(" cur_num=\"" + line.currentNum + "\">")

                        // For each word in the line...
                        word = line.firstWord
                        while (word.isValid) {
                            // Output the bounding box for the word.
                            bbox = word.bBox
                            mOutputListener!!.print("<Word box=\"" + String.format("%.2f, %.2f, %.2f, %.2f", bbox.x1, bbox.y1, bbox.x2, bbox.y2) + "\"")
                            mOutputListener!!.print(" cur_num=\"" + word.currentNum + "\"")
                            val sz = word.stringLen
                            if (sz == 0) {
                                word = word.nextWord
                                continue
                            }

                            // If the word style is different from the parent style, output the new style.
                            s = word.style
                            if (s != line_style) {
                                printStyle(s)
                            }

                            mOutputListener!!.print(">" + word.string)
                            mOutputListener!!.println("</Word>")
                            word = word.nextWord
                        }
                        mOutputListener!!.println("</Line>")
                        line = line.nextLine
                    }

                    if (cur_flow_id != -1) {
                        if (cur_para_id != -1) {
                            cur_para_id = -1
                            mOutputListener!!.println("</Para>")
                        }
                        mOutputListener!!.println("</Flow>")
                    }
                }
                txt.destroy()
                mOutputListener!!.println("</PDFText>")
            }
        } catch (e: PDFNetException) {
            mOutputListener!!.printError(e.stackTrace)
        }

        // Sample code showing how to use low-level text extraction APIs.
        if (example5_low_level) {
            try {
                PDFDoc(Utils.getAssetTempFile(PDFNetSample.INPUT_PATH + "newsletter.pdf")!!.absolutePath).use { doc ->
                    doc.initSecurityHandler()

                    // Example 1. Extract all text content from the document

                    val reader = ElementReader()
                    //  Read every page
                    val itr = doc.pageIterator
                    while (itr.hasNext()) {
                        reader.begin(itr.next())
                        DumpAllText(reader)
                        reader.end()
                    }

                    // Example 2. Extract text content based on the
                    // selection rectangle.
                    mOutputListener!!.print("\n----------------------------------------------------")
                    mOutputListener!!.print("\nExtract text based on the selection rectangle.")
                    mOutputListener!!.println("\n----------------------------------------------------")

                    val first_page = doc.pageIterator.next()!!
                    var s1 = ReadTextFromRect(first_page, Rect(27.0, 392.0, 563.0, 534.0), reader)
                    mOutputListener!!.print("\nField 1: $s1")

                    s1 = ReadTextFromRect(first_page, Rect(28.0, 551.0, 106.0, 623.0), reader)
                    mOutputListener!!.print("\nField 2: $s1")

                    s1 = ReadTextFromRect(first_page, Rect(208.0, 550.0, 387.0, 621.0), reader)
                    mOutputListener!!.print("\nField 3: $s1")

                    // ...
                    mOutputListener!!.println("Done.")
                }
            } catch (e: Exception) {
                mOutputListener!!.printError(e.stackTrace)
            }

        }

        for (file in mFileList) {
            addToFileList(file)
        }
        printFooter(outputListener)
    }

    companion object {

        private var mOutputListener: OutputListener? = null

        private val mFileList = ArrayList<String>()

        internal fun printStyle(s: TextExtractor.Style) {
            val r = s.color[0]
            val g = s.color[1]
            val b = s.color[2]
            val rgb_hex = String.format("%02X%02X%02X;", r, g, b)
            val df = DecimalFormat("#.#")
            mOutputListener!!.print(" style=\"font-family:" + s.fontName + "; "
                    + "font-size:" + df.format(s.fontSize) + ";"
                    + (if (s.isSerif) " sans-serif; " else " ")
                    + "color:#" + rgb_hex + "\"")
        }

        // A utility method used to dump all text content in the console window.
        @Throws(PDFNetException::class)
        internal fun DumpAllText(reader: ElementReader) {
            var element: Element?
            while (true) {
                element = reader.next()
                if (element == null) {
                    break
                }
                when (element.type) {
                    Element.e_text_begin -> mOutputListener!!.println("\n--> Text Block Begin")
                    Element.e_text_end -> mOutputListener!!.println("\n--> Text Block End")
                    Element.e_text -> {
                        val bbox = element.bBox
                        if (bbox != null) {
                            mOutputListener!!.println("\n--> BBox: " + bbox.x1 + ", "
                                    + bbox.y1 + ", "
                                    + bbox.x2 + ", "
                                    + bbox.y2)

                            val arr = element.textString
                            mOutputListener!!.println(arr)
                        }
                    }
                    Element.e_text_new_line -> mOutputListener!!.println("\n--> New Line")
                    Element.e_form                // Process form XObjects
                    -> {
                        reader.formBegin()
                        DumpAllText(reader)
                        reader.end()
                    }
                }
            }
        }

        // A helper method for ReadTextFromRect
        @Throws(PDFNetException::class)
        internal fun RectTextSearch(reader: ElementReader, pos: Rect): String {
            var element: Element?
            var srch_str = String()
            while (true) {
                element = reader.next()
                if (element == null) {
                    break
                }
                when (element.type) {
                    Element.e_text -> {
                        val bbox = element.bBox
                        if (bbox != null) {
                            if (bbox.intersectRect(bbox, pos)) {
                                val arr = element.textString
                                srch_str += arr
                                srch_str += "\n" // add a new line?
                            }
                        }
                    }
                    Element.e_text_new_line -> {
                    }
                    Element.e_form // Process form XObjects
                    -> {
                        reader.formBegin()
                        srch_str += RectTextSearch(reader, pos)
                        reader.end()
                    }
                }
            }
            return srch_str
        }

        // A utility method used to extract all text content from
        // a given selection rectangle. The rectangle coordinates are
        // expressed in PDF user/page coordinate system.
        @Throws(PDFNetException::class)
        internal fun ReadTextFromRect(page: Page, pos: Rect, reader: ElementReader): String {
            reader.begin(page)
            val srch_str = RectTextSearch(reader, pos)
            reader.end()
            return srch_str
        }
    }

}
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/android/get-started/samples/textextracttest.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
