Direct answer
RTF is a structured control-word stream, not plain text with braces that can be stripped by regular expression. Groups establish scoped character and paragraph state, destinations hold distinct document structures, and escaped bytes can affect how text is decoded. A brace counter alone will break on binary sections; splitting on backslashes will confuse control words, escaped symbols, and payload. Start with a pinned mature parser that actually supports the RTF subset you need, and test that exact artifact on Android. If no supported parser exposes the distinctions required by the product, reject or label the document unsupported rather than silently writing a partial parser. Name the source profile and projection. Microsoft RTF 1.9.1 describes a broad document format with many destinations and extensions; a text importer does not need to reproduce every Word layout feature. Define which main-story groups and related text sources are included, such as footnotes or endnotes, and what happens to headers, comments, bookmarks, annotations, tables, and alternate content. Preserve original bytes and record parser/version plus selected destination policy. Do not call a text projection a faithful Word rendering or claim that an Exchange-specific encapsulation algorithm applies to every RTF file. Unicode decoding requires state. The RTF Unicode escape token uN, written as a backslash followed by that control word, represents a signed 16-bit UTF-16 code unit; supplementary characters may be encoded as a high/low surrogate pair across Unicode escapes. The ucN setting is the number of ANSI fallback units a reader skips after a Unicode escape; it is not a count of Unicode grapheme clusters or source-file bytes. Its value is scoped by nested groups and restored at group exit. Count fallback tokens precisely: a control word or control symbol is one unit, and the delimiter space that terminates a control word is not a unit. A binN control word, its numeric argument, and its complete binary payload form one fallback unit; the reader must still skip the declared N raw payload bytes. If a group-opening or group-closing brace is encountered while fallback units remain, stop fallback skipping before the brace and process that brace normally under group rules. Add independent fixtures for each token form and boundary, plus negative uN values, surrogate pairs, nested ucN overrides, and restoration. Legacy text also depends on character-set controls. The header may declare a default ANSI code page, and font-table entries can assign code pages to selected fonts; a run may switch fonts later. Hex-escaped bytes must be decoded under the active code-page/font state, not as UTF-8 by assumption. Missing or unsupported code pages need a visible replacement/error policy, and the source bytes should remain available for comparison. Do not normalize text until after decoding decisions have been recorded; Unicode normalization is a separate product transformation and can change exact source sequences. Binary spans need byte-accurate treatment. The RTF binN control word, also introduced by a backslash, declares exactly N following raw bytes; braces, backslashes, and sequences that look like control words inside that span are payload, not grammar. Enforce a maximum declared length before skipping, use checked offsets, and reject truncation or overflow. Do not parse embedded pictures, objects, or binary data as though they were prose. Group parsing resumes only at the byte immediately after the declared span, so the implementation must distinguish byte offsets from decoded character positions. Destination policy is a content decision. A starred unknown destination may contain metadata or alternate text; the RTF reader rules commonly skip an unsupported starred destination as a whole group rather than leaking its tokens into the main text. Known destinations such as font tables and color tables are control metadata, not body prose. Fields can contain instruction text and a cached result: do not execute field instructions, external links, or embedded objects, and explicitly decide whether a supported cached result is included. Hidden text controls and revision-related material can also surprise a flat extractor. Define include/exclude behavior instead of assuming every text-like token is user-visible content. Keep parser output separate from model input. Produce a read-only projection with destination/group provenance, source offsets where the parser exposes them, decode warnings, and an explicit completeness label. Apply byte, nesting, token, destination, text, and elapsed-work bounds. Validate the projection for the intended task, show unsupported sections, and let the user review what will be sent to local processing. The parser and the local model are independent stages; local inference does not establish parser safety, and a successful parse does not authorize disclosure or make field results trustworthy. Test synthetic fixtures with independently prepared expected text: nested groups with state restoration, signed Unicode units and surrogate pairs, ucN values around plain ANSI fallback, an escaped control symbol, a control word and its terminating delimiter space, and binN with its argument and full raw payload. Add cases where an opening or closing group brace appears before the remaining fallback count is consumed; assert skipping stops before the brace and normal group handling continues. Also test font switches/code pages, unknown starred destinations, fields with both instruction and result, hidden text, binary spans containing brace-like bytes, truncated binN, invalid group closure, oversized input, and cancellation. Compare extracted values, omissions, source identity, and unchanged original bytes. The Microsoft Open Specifications extraction algorithm for original plain text is specifically about Exchange RTF encapsulation; cite it only for that email encapsulation case, not as a universal reader contract. This guide is a tested-subset method, not a claim that Cove imports RTF.
A legacy RTF note contains Unicode and an embedded field
A user selects an RTF note that mixes Chinese text, a supplementary-plane symbol, a nested font group, a field instruction with a cached result, and a picture destination containing bytes that resemble braces. A quick text dump duplicates fallback characters and leaks control metadata into the prompt.
Decision
Run the pinned parser with a declared text-only destination profile, correct Unicode/code-page state, bounded binary skipping, inert field handling, and a reviewable projection before model use.
Expected outcome
The app can identify exactly which source text was included or omitted, preserve the original document, and report unsupported content without pretending to render the RTF faithfully.
Evidence to collect
The claim becomes reviewable only when the following evidence is attached to the same artifact and test run:
- Pinned RTF parser and supported profile
- Group, code-page, Unicode, binN, and destination fixtures
- Source-preserving text projection and bounded failure outcomes
Task quality needs a versioned corpus and acceptance rules. Fluent sample output is not an accuracy result.
Implementation workflow
- Choose a real parser and supported subset. Record the parser artifact/version and its Android runtime path. Define accepted RTF revision, destinations, tables, fields, and error behavior; do not infer support from a file extension or write a brace-stripping parser.
- Track groups, code pages, and Unicode state. Test nested state restoration, active font/code page, signed UTF-16 units, surrogate pairs, and ucN ANSI fallback units. Count a control word or symbol as one unit, exclude its terminating delimiter space, treat binN plus its argument and whole payload as one unit while skipping N raw bytes, and stop fallback skipping before any group brace.
- Bound and skip binary spans safely. Check binN length before advancing byte offsets, cap it, and fail on overflow or truncation. Treat bytes inside the span as opaque payload so braces and backslashes do not alter group parsing.
- Apply destination and field policy. Select permitted text destinations, skip unsupported starred groups as whole groups, and never execute field instructions, links, or embedded objects. Specify hidden-text and cached-field-result handling.
- Review a provenance-bearing projection. Retain source identity, parser version, selected destinations, decode warnings, and completeness. Apply resource bounds, show included/omitted content, and confirm the original file is unchanged after success or failure.
Keep each transition observable. A failure should identify the stage, artifact, runtime, and recovery action without logging private user content.
Acceptance criteria
- The exact parser, supported RTF profile, destination policy, and unsupported-content outcome are named; no universal Android parser support is assumed.
- Nested group state, active code page/font, signed UTF-16 units, and surrogate pairs have independent fixtures; ucN tests count ANSI fallback tokens (not graphemes or bytes), exclude control-word delimiter space, handle binN as one unit plus N skipped payload bytes, stop before group braces, and restore scoped values.
- binN spans use checked byte bounds and cannot make braces/control-looking payload alter parser structure.
- Unknown starred destinations, fields, hidden text, and embedded objects follow explicit inert include/exclude rules.
- The extracted projection records source/parser provenance and limits; the original document is unchanged and no Cove import feature is claimed.
Decision table
| Dimension | Choice or evidence | How to interpret it |
|---|---|---|
| RTF main-story text projection | Use a pinned parser and explicit destination/code-page policy. | Recovers a supported text view without claiming complete layout, field execution, or every destination. |
| DOCX tracked-revision view | Select an original/proposed/review projection over WordprocessingML revision parts. | Revision markup is a package-level contract and does not define RTF group or Unicode fallback parsing. |
| EML MIME body decoding | Select a MIME part, transfer-decode bytes, then decode its charset. | MIME boundaries and transfer encodings are not RTF control-word groups or destination semantics. |
| Plain brace stripping | Do not use as an extraction method. | Nested groups, scoped state, escaped syntax, and raw binary spans make delimiters insufficient. |
Failure patterns to prevent
- Stripping syntax with regular expressions or brace counts
- Parsing binN bytes as control syntax
- Generalizing Exchange extraction rules to every RTF reader
Also prevent silent fallback, unpinned artifacts, missing cancellation, and conclusions that combine unlike configurations. Store unsuccessful runs alongside successful ones.
Minimum reproducibility record
| Layer | Record |
|---|---|
| Device | Manufacturer, model, chipset, RAM class, operating-system build |
| Software | Application version and git commit |
| Model | Family, variant, revision, format, file length, hash, quantization |
| Runtime | Name, revision, requested backend, observed backend evidence |
| Workload | Fixture revision, input hash, prompt hash, output policy |
| Outcome | Completed, failed, cancelled, fallback, and privacy-safe diagnostics |
Release checklist
- ☐ The primary query is answered without an unsupported number.
- ☐ Every artifact and runtime is pinned.
- ☐ The representative task and failure policy are explicit.
- ☐ Lifecycle, cancellation, cleanup, and fallback are tested.
- ☐ User-content and network boundaries are documented.
- ☐ Result wording applies only to the recorded configuration.
- ☐ The page links to raw method or evidence when results are added.
Sources and related evidence
- Android privacy and security
- Microsoft — Rich Text Format Specification, version 1.9.1
- Microsoft Learn — Extracting original plain text from Exchange RTF encapsulation
- Unicode Consortium — Unicode 16.0 Core Specification, UTF-16 and surrogates
Chinese deployment and troubleshooting content is organized in the .奇连 AI 端侧专题.
Frequently asked questions
What exactly does ucN count and what happens at a group brace?
It counts ANSI fallback units, not Unicode grapheme clusters or source bytes. A control word or symbol is one unit; its terminating delimiter space is not. binN with its argument and complete payload is one unit, while the reader also skips the declared raw payload bytes. If a group brace appears before the count is exhausted, stop fallback skipping and process the brace normally.
Can braces inside a binN span close an RTF group?
No. binN declares a raw byte span; exactly that many following bytes are payload. Check bounds and skip them opaquely before resuming grammar parsing.
Does an Exchange RTF extraction algorithm define all RTF text readers?
No. The cited MS-OXRTFEX text extraction procedure applies to original plain text encapsulated in Exchange RTF. General RTF import still needs a parser and a declared supported profile.
Should the importer include every text-like field or hidden run?
Not automatically. Field instructions may be executable or external references, and hidden/destination text can differ from the main story. Define a reviewed include/exclude policy and keep source provenance.