---
title: SAIF.Framework.Common.Files operations and processes
summary: Business and technical operations supported by this library.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-09-15
library: SAIF.Framework.Common.Files
reference_type: package
---

# SAIF.Framework.Common.Files operations and processes

This page is the operation catalog and cross-operation hub for this library. Each operation's detailed, step-by-step logic lives in its own page under `operations/`.

## Operation catalog

| Operation | Intent | Trigger | Inputs | Outputs | Rules |
| --- | --- | --- | --- | --- | --- |
| [Read a typed flat file](operations/read-typed-flat-file.md) | Map delimited/fixed-width file rows to POCO records via attribute or fluent configuration. | Caller calls `FileReader<TRecord>.Read(path)`. | File path; optional `FileFormats` or `IFileConfiguration`. | `IEnumerable<TRecord>`. | [BR-001](business-rules.md#br-001-default-configuration-required), [BR-002](business-rules.md#br-002-single-isdefault-configuration-required-among-multiple), [BR-003](business-rules.md#br-003-requested-format-must-match-a-declared-configuration), [BR-004](business-rules.md#br-004-trimall-trims-field-values-on-read), [BR-005](business-rules.md#br-005-quoted-field-handling-is-csv-only), [BR-006](business-rules.md#br-006-header-record-skipped-when-declared), [BR-007](business-rules.md#br-007-record-build-failures-report-layout-id-and-row-data), [BR-011](business-rules.md#br-011-record-derived-types-round-trip-the-raw-line), [BR-012](business-rules.md#br-012-delimited-layouts-use-1-based-element-ordinals) |
| [Read an untyped flat file](operations/read-untyped-flat-file.md) | Read a whole file into raw `Record`/`TabDelimitedRecord` rows without a typed configuration. | Caller calls `FileReader.Read(path)` / `FileReader.ReadDelimited(path, delimiter)`. | File path (+ delimiter for `ReadDelimited`). | `IEnumerable<IRecord>` / `IEnumerable<IDelimitedRecord>`. | [BR-013](business-rules.md#br-013-tabdelimitedrecord-always-splits-on-tab) |
| [Write a typed flat file](operations/write-typed-flat-file.md) | Serialise POCO records to a delimited or fixed-width file via attribute or fluent configuration. | Caller calls `FileWriter<TRecord>.Write(path, data)`. | Path or open `StreamWriter`, record collection, optional format/configuration. | Written file; no return value. | [BR-001](business-rules.md#br-001-default-configuration-required), [BR-008](business-rules.md#br-008-fixed-width-values-forced-to-layout-length), [BR-009](business-rules.md#br-009-header-field-must-have-a-property-or-title), [BR-010](business-rules.md#br-010-writable-layout-must-resolve-to-a-property), [BR-011](business-rules.md#br-011-record-derived-types-round-trip-the-raw-line), [BR-014](business-rules.md#br-014-no-trailing-delimiter-in-delimited-output), [BR-015](business-rules.md#br-015-output-value-resolution-order) |
| [Configure a layout fluently](operations/configure-layout-fluently.md) | Provide a code-first alternative to attribute-based layout declaration. | Consumer subclasses `FileConfiguration<T>` and calls builder methods in its constructor. | Lambda property expressions. | An `IFileConfiguration` usable by read/write. | [BR-016](business-rules.md#br-016-readcustom-and-writecustom-force-layout-direction) |
| [Read an EDI interchange file](operations/read-edi-interchange-file.md) | Parse a physical EDI file into a populated `EdiFile` with segments and the functional-group hierarchy. | Caller calls `EdiManager.File().Path(p).Read()`. | File path. | Populated `EdiFile`. | [BR-017](business-rules.md#br-017-physical-line-breaks-are-not-significant), [BR-029](business-rules.md#br-029-first-isa-and-iea-are-the-interchange-header-and-trailer), [BR-030](business-rules.md#br-030-functional-groups-built-only-when-all-four-control-segments-present) |
| [Parse EDI text into segments and elements](operations/parse-edi-text-into-segments-and-elements.md) | Lexically split raw EDI text into segments, data elements, and composite sub-elements. | Called by the EDI file read operation, or directly by a consumer. | Raw EDI string. | `List<IEdiSegment>`. | [BR-018](business-rules.md#br-018-segments-delimited-by-tilde-empty-segments-discarded), [BR-019](business-rules.md#br-019-colon-containing-elements-become-composite-elements), [BR-020](business-rules.md#br-020-first-element-is-the-segment-identifier) |
| [Serialise segments and elements](operations/serialise-segments-and-elements.md) | Build ordered `IEdiDataElement` collections into an X12 segment text fragment. | `ISegmentData.Build()`, `EdiSegment.ToString()`, EDI file write. | Ordered data elements. | EDI text fragment. | [BR-021](business-rules.md#br-021-segment-construction-requires-a-non-null-element-list), [BR-022](business-rules.md#br-022-only-one-identifying-element-at-index-0), [BR-023](business-rules.md#br-023-segment-id-must-not-be-blank), [BR-024](business-rules.md#br-024-null-element-values-are-omitted), [BR-025](business-rules.md#br-025-composite-sub-elements-require-a-composite-parent), [BR-026](business-rules.md#br-026-composite-element-values-joined-with-colon), [BR-027](business-rules.md#br-027-skipped-element-ordinals-preserved-with-placeholders), [BR-028](business-rules.md#br-028-simple-data-element-terminated-by-asterisk) |
| [Build the X12 envelope hierarchy](operations/build-x12-envelope-hierarchy.md) | Convert a flat, index-ordered segment list into the interchange → functional group → transaction set → hierarchical transaction → hierarchical level tree. | `SetSegments`, `Add` of a control segment, or first access to `EdiFile.FunctionalGroups`. | Flat segment list. | `IFunctionalGroupContainer` tree. | [BR-029](business-rules.md#br-029-first-isa-and-iea-are-the-interchange-header-and-trailer), [BR-030](business-rules.md#br-030-functional-groups-built-only-when-all-four-control-segments-present), [BR-031](business-rules.md#br-031-every-added-segment-receives-the-next-sequential-index), [BR-032](business-rules.md#br-032-adding-a-control-segment-re-derives-envelope-groupings), [BR-033](business-rules.md#br-033-control-segments-excluded-from-member-segments-collections), [BR-034](business-rules.md#br-034-group-keys-derived-from-control-number-elements), [BR-035](business-rules.md#br-035-hierarchical-levels-nested-inside-hierarchical-transaction), [BR-036](business-rules.md#br-036-segment-group-ownership-determined-by-position) |
| [Write an EDI interchange file](operations/write-edi-interchange-file.md) | Serialise an `IEdiFile`'s segments to a single-line EDI text file. | Caller calls `EdiFileBuilder.Write(file)`. | `IEdiFile`. | Single-line EDI text file at the target path. | [BR-027](business-rules.md#br-027-skipped-element-ordinals-preserved-with-placeholders), [BR-037](business-rules.md#br-037-edi-interchange-written-as-a-single-line-overwriting-existing-file) |
| [Map a segment to/from a typed segment object](operations/map-segment-to-typed-object.md) | Convert between an untyped `IEdiSegment` and a strongly-typed segment object (`ISegmentData`). | `EdiGroupParser` (for envelope segments) or application code. | An `IEdiSegment` (read) or populated properties (write). | A typed segment object or a built `IEdiSegment`. | [BR-038](business-rules.md#br-038-isa-header-fixed-qualifiers-and-padding), [BR-039](business-rules.md#br-039-isa-acknowledgement-request-flag), [BR-040](business-rules.md#br-040-gs-header-responsible-agency-code-and-batch-date-time), [BR-041](business-rules.md#br-041-st-and-se-control-numbers-zero-padded-to-four-digits), [BR-042](business-rules.md#br-042-ak2-control-number-zero-padded-to-four-digits), [BR-043](business-rules.md#br-043-iea-control-number-emitted-as-nine-digits), [BR-044](business-rules.md#br-044-bht-original-vs-reissue-flag), [BR-045](business-rules.md#br-045-dtp-format-defaults), [BR-046](business-rules.md#br-046-dtp-values-interpreted-by-format-qualifier), [BR-047](business-rules.md#br-047-nm1-person-vs-organization-name-layout), [BR-048](business-rules.md#br-048-nm1-complete-name-composition), [BR-049](business-rules.md#br-049-n4-postal-code-split-into-zip-and-extension), [BR-050](business-rules.md#br-050-ctx-amounts-scaled-to-cents-cas-amounts-unscaled), [BR-051](business-rules.md#br-051-svc-adjudication-suppression-rules), [BR-052](business-rules.md#br-052-hl-child-level-indicator), [BR-053](business-rules.md#br-053-ik5-acknowledgement-or-reject-response-codes), [BR-054](business-rules.md#br-054-dmg-hi-sv1-sv2-sv3-are-inbound-only-segments), [BR-059](business-rules.md#br-059-optional-segment-elements-written-only-when-populated), [BR-060](business-rules.md#br-060-sv1-emergency-indicator-conditions), [BR-061](business-rules.md#br-061-cas-and-ctx-adjustment-triplets), [BR-062](business-rules.md#br-062-procedure-composite-equality-excludes-description) |
| [Generate an outbound EDI file name](operations/generate-outbound-edi-file-name.md) | Produce a timestamped, environment-tagged file name for an outbound EDI file. | Caller request prior to writing an EDI file. | `fileType`, `isProd`. | Formatted file name string. | [BR-055](business-rules.md#br-055-generated-edi-file-name-pattern) |
| [Convert EDI date/time strings](operations/convert-edi-date-time-strings.md) | Convert between EDI date/time string representations and `DateTime`. | `Fill`/`Build` of every date-bearing segment (BHT, GS, ISA, DTM, DTP, BPR, DMG, HI, STC). | EDI date/time strings. | `DateTime` values (and the reverse). | [BR-056](business-rules.md#br-056-two-digit-edi-years-interpreted-as-21st-century), [BR-057](business-rules.md#br-057-edi-time-value-right-padded-before-conversion), [BR-058](business-rules.md#br-058-edi-date-range-format) |

## Process flow diagram
The following diagram visualizes the primary operational flow for the EDI subsystem, from reading a file through envelope grouping and typed segment mapping.

```mermaid
flowchart TD
	Start([Caller requests EDI read]) --> Read[Read an EDI interchange file]
	Read --> Parse["Parse EDI text into<br>segments and elements"]
	Parse --> Group[Build the X12 envelope hierarchy]
	Group --> Map["Map a segment to/from<br>a typed segment object"]
	Map --> Decision{Consumer modifies typed segments?}
	Decision -->|Yes| Serialise[Serialise segments and elements]
	Serialise --> Write[Write an EDI interchange file]
	Decision -->|No| EndRead(["Typed segment objects<br>returned to caller"])
	Write --> EndWrite([Single-line EDI file written])
```

## Failure and edge-case behavior
- `FileReader<TRecord>.Read`/`FileWriter<TRecord>.Write` throw `ApplicationException` when no resolvable configuration exists ([BR-001](business-rules.md#br-001-default-configuration-required), [BR-002](business-rules.md#br-002-single-isdefault-configuration-required-among-multiple), [BR-003](business-rules.md#br-003-requested-format-must-match-a-declared-configuration)); `FileWriter<TRecord>.Write(string, IEnumerable<TRecord>)` throws this exception unconditionally, even after a successful write, because the throw sits outside the success-path `if` block.*
- `FileReader<TRecord>.BuildRecord` wraps any per-row mapping failure in an `ApplicationException` carrying the layout id and raw row data ([BR-007](business-rules.md#br-007-record-build-failures-report-layout-id-and-row-data)).
- `SegmentBuilder` throws `ApplicationException` for a duplicate identifying element ([BR-022](business-rules.md#br-022-only-one-identifying-element-at-index-0)) or a composite sub-element added to a non-composite parent ([BR-025](business-rules.md#br-025-composite-sub-elements-require-a-composite-parent)), and an `ArgumentException` for a null element list or blank segment id ([BR-021](business-rules.md#br-021-segment-construction-requires-a-non-null-element-list), [BR-023](business-rules.md#br-023-segment-id-must-not-be-blank)).
- `EdiFile.RefreshGroupings` silently leaves the functional-group tree unbuilt when `ISA`/`IEA`/`GS`/`GE` are not all present, rather than throwing ([BR-030](business-rules.md#br-030-functional-groups-built-only-when-all-four-control-segments-present)).
- `DmgSegment.Build`, `HiSegment.Build`, `Sv1Segment.Build`, `Sv2Segment.Build`, and `Sv3Segment.Build` always throw `NotImplementedException` because those segments are inbound-only ([BR-054](business-rules.md#br-054-dmg-hi-sv1-sv2-sv3-are-inbound-only-segments)).
- `SvcSegment.Parse` returns an `Sv1Segment` instance instead of an `SvcSegment` — a likely copy/paste defect with no in-repo consumer available to confirm impact.*

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Business rules](business-rules.md)
- [API reference](api/index.md)

> **Note:** Statements marked with `*` were inferred from code structure, naming
> conventions, or contextual evidence where direct confirmation was not available
> in source artifacts.

## Sources
- Common\SAIF.Common.Files\Core\FileReader.cs
- Common\SAIF.Common.Files\Core\FileWriter.cs
- Common\SAIF.Common.Files\Core\Configurations\FileConfiguration.cs
- Common\SAIF.Common.Files\Edi\EdiManager.cs
- Common\SAIF.Common.Files\Edi\Core\Builders\EdiFileBuilder.cs
- Common\SAIF.Common.Files\Edi\Core\Readers\EdiFileReader.cs
- Common\SAIF.Common.Files\Edi\Core\Parsers\EdiSegmentParser.cs
- Common\SAIF.Common.Files\Edi\Core\Parsers\EdiGroupParser.cs
- Common\SAIF.Common.Files\Edi\Core\Builders\SegmentBuilder.cs
- Common\SAIF.Common.Files\Edi\Core\Builders\EdiRecordBuilder.cs
- Common\SAIF.Common.Files\Edi\Core\Writers\EdiFileWriter.cs
- Common\SAIF.Common.Files\Edi\NameBuilder.cs
- Common\SAIF.Common.Files\Edi\Core\DateMaker.cs
- Common\SAIF.Common.Files\Edi\Segments\SvcSegment.cs
