Recursive AI

Read a Word DOCX document in C#

OneDocument is a free, open-source Word, Excel and PowerPoint document library for .NET from Recursive AI. MIT or Apache-2.0, no native dependencies.

Terminal
dotnet add package \
    RecursiveAI.OneDocument.Documents

Requires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.

C#
using RecursiveAI.OneDocument;
var t = Office.ExtractText("report.docx");
Console.WriteLine(t);

Prints the document’s plain text.

Download this example (.zip): unzip, then dotnet run.

The full program

The download creates report.docx, reads its paragraphs with their style names, and then extracts plain text from the same file.

C#
using RecursiveAI.OneDocument;
using RecursiveAI.OneDocument.Documents;
 
using (Document made = Document.Create())
{
    made.Body.AddParagraph("Site visit report");
    made.Body.AddParagraph("Replace the stairwell light by Friday.");
    made.SaveAs("report.docx");
}
 
using Document doc = Document.Open("report.docx");
foreach (Paragraph paragraph in doc.Paragraphs)
    Console.WriteLine($"[{paragraph.Style}] {paragraph.Text}");
Console.WriteLine("Plain text:");
Console.WriteLine(Office.ExtractText("report.docx").Trim());

dotnet run prints:

Text
[Normal] 
[Normal] Site visit report
[Normal] Replace the stairwell light by Friday.
Plain text:
Site visit report
Replace the stairwell light by Friday.

A newly created document starts with an empty paragraph, so the first printed paragraph is blank. A damaged main XML part raises OfficeFormatException during text extraction; it is not treated as an empty document.

Variations

Skip blank paragraphs.

C#
using RecursiveAI.OneDocument.Documents;
 
using var doc = Document.Open("report.docx");
foreach (var p in doc.Paragraphs)
    if (!string.IsNullOrWhiteSpace(p.Text))
        Console.WriteLine(p.Text);
Text
Site visit report
Replace the stairwell light by Friday.

The short answer

To read a Word DOCX document in C#, reference OneDocument’s Documents package. Use Office.ExtractText when you want a string, or Document.Open and doc.Paragraphs when you need paragraph text and style names. Neither route requires opening Word. The download makes a small Word file first, so you can run both approaches against the same input.

These APIs answer different questions. Text extraction is useful for searching, indexing and feeding plain text into another part of an application. The document model is useful when the surrounding paragraph structure matters or when you intend to edit the file afterward. A plain-text string does not preserve page geometry or the original Word formatting.

How do I read a Word DOCX file in C#?

The full program opens report.docx with Document.Open, iterates paragraphs, and prints each paragraph’s style and text. The initial empty Normal paragraph is real: a new document starts with an empty paragraph. The variation filters whitespace-only paragraphs when your application only wants paragraphs with visible text.

Do not treat those paragraphs as fixed visual lines. A long paragraph can wrap onto several lines or pages depending on the page width and fonts. A line-oriented import based on Paragraphs is therefore an import of logical paragraphs, not the lines you see on a printed page. If you need page positions, that is a layout task rather than a text-reading task.

Opening identifies the format from its content, not merely its extension. Keep the using statement so the document is disposed when reading finishes. Reading alone does not require saving the file. See authoring for the model and editing behavior.

How can I read a file into a string in C#?

For a supported Word file, use Office.ExtractText, not a generic text-file reader. The text extraction documentation defines what the returned text includes. Paragraphs end in line feeds. Tabs remain tabs. Field results are included, but field instructions are not. Table rows become lines with tab-separated cells, and paragraphs inside a table cell are flattened into that cell.

Extraction also has defaults that matter when you index documents. Headers, footers, notes and comments are included by default. The extraction docs say: “inserted and moved-to text is text; deleted and moved-from text (w:del, w:moveFrom) is left out unless IncludeDeletedText.” Set TextExtractionOptions.IncludeDeletedText to true when you need deleted text too. List labels are off by default because the streaming extractor does not build the numbering definitions. If you need visible numbering, use the document-backed list label source described in those docs rather than assuming that a paragraph’s text includes its bullet or number.

The sample calls Trim only when printing the extracted text in the full program. That makes the console output easier to read by removing leading and trailing whitespace. It is a presentation choice, not a required extraction step; keep the untrimmed string when those boundary line feeds matter to your own processing.

Can I read old .doc files?

Yes. The README’s format table marks DOC as read-only: you can read its contents, but cannot save edits back as DOC. PPT is also read-only; that is a separate presentation format, not a Word file. For this recipe, use DOCX as the generated and editable format and choose text extraction only when plain text is the output you actually need.

Opening identifies the input from its content, so the Documents package can read a supported binary DOC through the same document APIs. A DOC or DOCX is not a plain text file: OneDocument reads the document structure and interprets it to extract text. The extraction docs describe how package-based DOCX extraction streams the relevant parts instead of building the editable model.

All onedocument recipes