AnkiIO 1.0.2
Build, validate, import, and export Anki-compatible decks from .NET
Loading...
Searching...
No Matches
AnkiIO.AnkiPackageWriter Class Reference

Writes validated deck data as a legacy-compatible .apkg archive accepted by Anki 26.05. More...

Static Public Member Functions

static async Task WriteAsync (AnkiDeck deck, string path, CancellationToken cancellationToken=default)
 Writes one deck hierarchy to a package file without opening or modifying an Anki profile.
static async Task WriteAsync (AnkiPackage package, string path, CancellationToken cancellationToken=default)
 Writes every hierarchy and all retained media in a previously read package to a package file.
static async Task WriteAsync (AnkiDeck deck, Stream destination, CancellationToken cancellationToken=default)
 Writes one deck hierarchy to a writable caller-owned stream and leaves the stream open.
static async Task WriteAsync (AnkiPackage package, Stream destination, CancellationToken cancellationToken=default)
 Writes every hierarchy and all retained media in a package to a caller-owned stream and leaves it open.

Detailed Description

Writes validated deck data as a legacy-compatible .apkg archive accepted by Anki 26.05.

Choose a deck overload for a newly constructed hierarchy: it writes that root, its descendants, and media registered on those decks. Choose a package overload for read-modify-write: it writes every root and combines AnkiPackage.Media with deck media. Passing only package.Decks[0] intentionally omits other roots and package-only media.

Output contains collection.anki2 with schema-11 JSON metadata, a fixed scheduler-version-2 configuration, and a traditional numeric media map. Anki 26.05 was verified to import this representation. The writer does not emit native collection.anki21b, schema-18 protobuf metadata, or meta, and does not produce byte-identical Anki exports. A fixed default deck configuration is emitted; deck options, AnkiDeck.Metadata, AnkiDeck.UnknownData, and unsupported storage columns are not preserved. Review rows are written, but AnkiReviewLog.ReviewedAt is not independently encoded; AnkiReviewLog.Id becomes the legacy review-log key.

Every graph is validated before archive output begins. Identical case-sensitive media names with equal length and SHA-256 are coalesced; conflicting content is rejected. Path-backed media is rehashed while writing and rejected if it changed after registration. Do not mutate graphs, note types, cards, review histories, media collections, or backing files during a write. Separate calls have no shared mutable writer state and may run concurrently with separate inputs. Write timestamps make output semantically repeatable but not byte-for-byte deterministic.

Create a new deck and write it atomically to a path:

var deck = new AnkiDeck("Spanish");
deck.AddBasicNote("hola", "hello");
await AnkiPackageWriter.WriteAsync(deck, "spanish.apkg");
Builds one named deck hierarchy and acts as the root for validation and export.
Definition AnkiDeck.cs:31
Writes validated deck data as a legacy-compatible .apkg archive accepted by Anki 26....
static async Task WriteAsync(AnkiDeck deck, string path, CancellationToken cancellationToken=default)
Writes one deck hierarchy to a package file without opening or modifying an Anki profile.

Preserve package-level media while modifying an existing package:

var package = await AnkiPackageReader.ReadAsync("input.apkg");
package.Decks[0].AddBasicNote("adiós", "goodbye");
await AnkiPackageWriter.WriteAsync(package, "output.apkg");

Definition at line 48 of file AnkiPackageWriter.cs.

Member Function Documentation

◆ WriteAsync() [1/4]

async Task AnkiIO.AnkiPackageWriter.WriteAsync ( AnkiDeck deck,
Stream destination,
CancellationToken cancellationToken = default )
inlinestatic

Writes one deck hierarchy to a writable caller-owned stream and leaves the stream open.

Parameters
deckThe single root deck whose complete descendant hierarchy will be written.
destinationA writable stream positioned where the ZIP archive should begin.
cancellationTokenCancels database creation and asynchronous archive or media I/O.
Returns
A task that completes after the archive and its central directory have been finalized.

The caller owns and must eventually dispose destination ; this method leaves it open on success or failure. Seeking is not required. Archive bytes begin at the current position, the original position is not restored, and existing content is not truncated. Before reusing a seekable stream, normally set Position = 0 and SetLength(0). Validation and media-collision checks occur before the first write. Failures after output begins can leave partial ZIP bytes, so use the path overload when transactional replacement matters. Do not access the stream concurrently.

Exceptions
ArgumentNullExceptiondeck or destination is null.
ArgumentExceptiondestination is not writable.
ObjectDisposedExceptiondestination or a path-backed media stream has been disposed.
AnkiValidationExceptiondeck violates a checked domain invariant.
FileNotFoundExceptionA path-backed media source no longer exists.
DirectoryNotFoundExceptionA registered media directory does not exist.
UnauthorizedAccessExceptionA media source or the temporary workspace cannot be accessed.
InvalidDataExceptionA path-backed media payload no longer matches its registration-time SHA-256 digest.
Microsoft.Data.Sqlite.SqliteExceptionThe temporary legacy collection database cannot be created or populated.
InvalidOperationExceptionMedia filenames collide with different content, or mutable input changes during enumeration.
NotSupportedExceptiondestination does not support a required write operation.
IOExceptionThe destination, media, or temporary workspace cannot be read, written, finalized, or removed.
OperationCanceledExceptioncancellationToken is canceled.

Definition at line 143 of file AnkiPackageWriter.cs.

◆ WriteAsync() [2/4]

async Task AnkiIO.AnkiPackageWriter.WriteAsync ( AnkiDeck deck,
string path,
CancellationToken cancellationToken = default )
inlinestatic

Writes one deck hierarchy to a package file without opening or modifying an Anki profile.

Parameters
deckThe single root deck whose complete descendant hierarchy will be written.
pathThe destination package path. The extension is not validated.
cancellationTokenCancels database creation and asynchronous archive or media I/O.
Returns
A task that completes after the archive has been finalized and committed to the destination path.

The graph and media-name collisions are validated before a destination or temporary output file is opened. The complete archive is built in a uniquely named file beside path , closed, then committed with one same-directory overwrite move. Until that move, an existing destination is never opened or truncated; a missing destination remains absent. Failures or cancellation before commit leave the previous destination unchanged and the temporary file is removed. The move provides filesystem rename atomicity, not a backup or a guarantee against power loss. Parent directories are not created, and the filename extension is not enforced.

Exceptions
ArgumentNullExceptiondeck or path is null.
ArgumentExceptionpath is blank or has invalid path syntax.
PathTooLongExceptionpath or a registered media path exceeds a platform path-length limit.
DirectoryNotFoundExceptionThe destination parent or a registered media directory does not exist.
FileNotFoundExceptionA path-backed media source no longer exists.
UnauthorizedAccessExceptionThe destination, a media source, or the temporary workspace cannot be accessed.
AnkiValidationExceptiondeck violates a checked domain invariant.
InvalidDataExceptionA path-backed media payload no longer matches its registration-time SHA-256 digest.
Microsoft.Data.Sqlite.SqliteExceptionThe temporary legacy collection database cannot be created or populated.
InvalidOperationExceptionMedia filenames collide with different content, or mutable input changes during enumeration.
IOExceptionThe destination, media, or temporary workspace cannot be read, written, finalized, replaced, or removed.
OperationCanceledExceptioncancellationToken is canceled.

Definition at line 75 of file AnkiPackageWriter.cs.

◆ WriteAsync() [3/4]

async Task AnkiIO.AnkiPackageWriter.WriteAsync ( AnkiPackage package,
Stream destination,
CancellationToken cancellationToken = default )
inlinestatic

Writes every hierarchy and all retained media in a package to a caller-owned stream and leaves it open.

Parameters
packageThe package whose top-level deck hierarchies and package-level media will be written.
destinationA writable stream positioned where the ZIP archive should begin.
cancellationTokenCancels database creation and asynchronous archive or media I/O.
Returns
A task that completes after the archive and its central directory have been finalized.

Use this overload for supported read-modify-write workflows. Every registration in AnkiPackage.Media is combined with media on all package deck hierarchies. The caller owns and must dispose destination ; the method leaves it open on success or failure. Seeking is not required. Output starts at the current position, existing content is not truncated, and the original position is not restored. Validation occurs before the first write, but database, media, cancellation, or I/O failure afterward can leave partial ZIP bytes. Use the path overload when an existing artifact must remain unchanged on failure.

Exceptions
ArgumentNullExceptionpackage or destination is null.
ArgumentExceptionpackage contains no top-level decks, or destination is not writable.
ObjectDisposedExceptiondestination or a path-backed media stream has been disposed.
AnkiValidationExceptionA hierarchy in package violates a checked domain invariant.
FileNotFoundExceptionA path-backed media source no longer exists.
DirectoryNotFoundExceptionA registered media directory does not exist.
UnauthorizedAccessExceptionA media source or the temporary workspace cannot be accessed.
InvalidDataExceptionA path-backed media payload no longer matches its registration-time SHA-256 digest.
Microsoft.Data.Sqlite.SqliteExceptionThe temporary legacy collection database cannot be created or populated.
InvalidOperationExceptionMedia filenames collide with different content, or mutable input changes during enumeration.
NotSupportedExceptiondestination does not support a required write operation.
IOExceptionThe destination, media, or temporary workspace cannot be read, written, finalized, or removed.
OperationCanceledExceptioncancellationToken is canceled.

Definition at line 178 of file AnkiPackageWriter.cs.

◆ WriteAsync() [4/4]

async Task AnkiIO.AnkiPackageWriter.WriteAsync ( AnkiPackage package,
string path,
CancellationToken cancellationToken = default )
inlinestatic

Writes every hierarchy and all retained media in a previously read package to a package file.

Parameters
packageThe package whose top-level deck hierarchies and package-level media will be written.
pathThe destination package path. The extension is not validated.
cancellationTokenCancels database creation and asynchronous archive or media I/O.
Returns
A task that completes after the archive has been finalized and committed to the destination path.

Use this overload for supported read-modify-write workflows. It includes every registration in AnkiPackage.Media as well as registrations added to any deck in AnkiPackage.Decks. Identical duplicate registrations are coalesced; conflicting registrations and invalid graphs are rejected before output is opened. The complete archive is closed in a same-directory temporary file and committed with one overwrite move. Failure before commit leaves an existing destination unchanged, and temporary output is removed. This is lossless only for the explicitly supported fields described by AnkiPackageReader; unsupported Anki storage data discarded during reading cannot be recovered by this method.

Exceptions
ArgumentNullExceptionpackage or path is null.
ArgumentExceptionpackage contains no top-level decks, or path is blank or invalid.
PathTooLongExceptionpath or a registered media path exceeds a platform path-length limit.
DirectoryNotFoundExceptionThe destination parent or a registered media directory does not exist.
FileNotFoundExceptionA path-backed media source no longer exists.
UnauthorizedAccessExceptionThe destination, a media source, or the temporary workspace cannot be accessed.
AnkiValidationExceptionA hierarchy in package violates a checked domain invariant.
InvalidDataExceptionA path-backed media payload no longer matches its registration-time SHA-256 digest.
Microsoft.Data.Sqlite.SqliteExceptionThe temporary legacy collection database cannot be created or populated.
InvalidOperationExceptionMedia filenames collide with different content, or mutable input changes during enumeration.
IOExceptionThe destination, media, or temporary workspace cannot be read, written, finalized, replaced, or removed.
OperationCanceledExceptioncancellationToken is canceled.

Definition at line 109 of file AnkiPackageWriter.cs.


The documentation for this class was generated from the following file: