# DATEV exporter for Java — full documentation
Release 0.2.0. Source: https://github.com/mrtyldr/datev-exporter
Java 17 library that generates, validates and streams DATEV Buchungsstapel / EXTF v13 and v12 files. It is a format exporter, not an accounting engine, DATEV API client, SKR03/SKR04 mapper or import certification service. Generated files are import candidates; acceptance must be verified in the licensed, configured target environment.
This project is independent and is not affiliated with, endorsed by or supported by DATEV. DATEV is a trademark of DATEV eG.
---
Source: https://mrtyldr.github.io/datev-exporter/en/
Java 17 · Apache-2.0 · release 0.2.0
# Own your booking data. Reuse the format layer.
Turn already-mapped booking data into deterministic DATEV Buchungsstapel / EXTF files—with fixed v13/v12 schemas, typed metadata, technical validation and forward-only streaming.
The contract
## Format exporter, not accounting engine.
Your application supplies mapped accounts, amounts, dates and business decisions. The library supplies the EXTF management record, official column order, CSV encoding and deterministic technical checks.
Read the exact limitations →
Why it exists
## The hard part is not joining values with semicolons.
A complete Buchungsstapel file combines a differently shaped management record, an exact versioned heading and tightly formatted booking rows. Small drift in width, order, quoting, line endings or encoding can make an otherwise valid export unusable.
### Keep the schema canonical
Use one ordered definition for all 125 v13 fields and the 124-field legacy v12 shape instead of maintaining a private spreadsheet or array.
### Fail before bytes drift
Reject structural, Windows-1252 and optional semantic violations before a booking row is committed to the destination.
### Choose the memory model
Retain rows when they must be inspected or replayed; stream them forward once when export volume makes retention unnecessary.
What ships
## A narrow API around a precise output contract.
The common path stays dependency-light. Optional modules are explicit, so a Univocity dependency or semantic validator appears only when you choose it.
Recommended default
### Plain fixed-schema exporter
Complete v13/v12 EXTF output, retained DatevFile and the forward-only DatevStreamWriter. Choose this unless the receiving contract intentionally differs from the official heading.
Start with plain →
Custom downstream CSV
### Advanced exporter
Rename, reorder or replace headings and select validation mode per file. Custom headings cannot be combined with EXTF metadata because they are no longer the fixed DATEV schema.
Compare exporters →
Existing pipeline only
### Univocity adapter
Route heading-and-row output through an existing Univocity CsvWriter. It cannot emit the differently shaped management record and quotes official text headings differently.
Understand the boundary →
A deliberate boundary
## Your domain in. An import candidate out.
### Map in your application
Resolve chart of accounts, tax treatment, master data and client-specific rules before calling the exporter.
### Assemble and validate
Attach typed metadata, write named or typed columns, and select metadata-aware technical validation.
### Verify in the target
Move the generated file through your controlled transfer process and verify acceptance in the licensed, configured DATEV environment.
Passing library validation—or matching the checked v13 schema and sample contract—does not prove accounting correctness or acceptance by a specific DATEV product, tenant or configuration.
Evidence, not adjectives
## Compatibility claims are graded.
For v13, an opt-in contract test pins DATEV’s official checker schema and official sample archive, compares the 125 field definitions and validates all 54 sample booking rows. It does not turn a Windows GUI launch into a pass/fail import result.
For v12, the library supports the 124-column prefix and matching management record, but currently has no independent official v12 fixture or recorded real-import acceptance evidence.
See the compatibility matrix
Continue exploring
### Use evidence at the right layer
- Complete v13 example
- v12/v13 evidence matrix
- Validation layers
- Reproducible benchmarks
- Versioned Java API
---
Source: https://mrtyldr.github.io/datev-exporter/en/getting-started.html
Getting started · 0.2.0
# From mapped bookings to a complete EXTF file.
Start with the fixed-schema plain exporter. Add typed metadata and metadata-aware validation, then choose retained or forward-only output based on your lifecycle.
Step 0
## Requirements and module choice
- Java 17 or newer.
- datev-exporter-plain for the fixed v13/v12 schemas and output.
- datev-exporter-field-validator when deterministic semantic checks should run before each row is accepted.
The root datev-exporter artifact is a Bill of Materials (BOM), not a runtime JAR. Import it to keep module versions aligned, then depend on the modules you use.
The examples use placeholder adviser/client numbers and account assignments. Replace every business value with data approved for your target ledger; the library does not map SKR03/SKR04 or determine tax treatment.
Step 1A
## Run with Gradle
Create a Java application, place the Java example below in src/main/java/Example.java, then use this build.gradle:
```
plugins {
id 'application'
}
repositories {
mavenCentral()
}
dependencies {
implementation platform('io.github.mrtyldr:datev-exporter:0.2.0')
implementation 'io.github.mrtyldr:datev-exporter-plain'
implementation 'io.github.mrtyldr:datev-exporter-field-validator'
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
application {
mainClass = 'Example'
}
```
Run it with your Gradle wrapper:
```
./gradlew run
```
The repository also contains a deterministic, CI-executed application:
```
git clone https://github.com/mrtyldr/datev-exporter.git
cd datev-exporter
./gradlew :examples:quickstart-gradle:run
```
Step 1B
## Build with Maven
The same Example.java works with this minimal pom.xml. The BOM owns the module versions:
```
4.0.0
example
datev-quickstart
1.0.0
17
UTF-8
io.github.mrtyldr
datev-exporter
0.2.0
pom
import
io.github.mrtyldr
datev-exporter-plain
io.github.mrtyldr
datev-exporter-field-validator
org.apache.maven.plugins
maven-compiler-plugin
3.15.0
org.codehaus.mojo
exec-maven-plugin
3.6.3
Example
```
Compile and run with:
```
mvn verify exec:java
```
Step 2
## Create a complete v13 file
This application writes all three required record layers: EXTF management record, the exact 125-column v13 heading, and one booking row. DatevFile retains accepted rows so they can be inspected or written again.
```
import io.github.mrtyldr.datev.core.DatevColumn;
import io.github.mrtyldr.datev.core.DatevField;
import io.github.mrtyldr.datev.core.DatevMetadata;
import io.github.mrtyldr.datev.core.DatevValidationContext;
import io.github.mrtyldr.datev.plain.DatevFile;
import io.github.mrtyldr.datev.validation.DatevValidator;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.time.LocalDateTime;
public final class Example {
public static void main(String[] args) throws Exception {
LocalDate fiscalStart = LocalDate.of(2026, 1, 1);
LocalDate periodStart = LocalDate.of(2026, 8, 1);
LocalDate periodEnd = LocalDate.of(2026, 8, 31);
DatevMetadata metadata = DatevMetadata.bookingBatchV13()
.createdAt(LocalDateTime.now())
.origin("RE")
.exportedBy("my_application")
.advisorNumber(1001)
.clientNumber(1)
.fiscalYearStart(fiscalStart)
.accountLength(4)
.period(periodStart, periodEnd)
.description("August 2026")
.applicationInformation("my-application")
.build();
DatevValidationContext context = DatevValidationContext.builder()
.accountLength(metadata.accountLength())
.fiscalYearStart(metadata.fiscalYearStart())
.period(metadata.periodStart(), metadata.periodEnd())
.build();
DatevValidator validator = DatevValidator.builder()
.context(context)
.build();
DatevFile file = DatevFile.builder()
.metadata(metadata)
.validator(validator)
.build();
file.append(
DatevColumn.amount(DatevField.AMOUNT,
new BigDecimal("1250.00")),
DatevColumn.of(DatevField.DEBIT_CREDIT_FLAG, "S"),
DatevColumn.of(DatevField.CURRENCY, "EUR"),
DatevColumn.account(DatevField.ACCOUNT, 1000),
DatevColumn.account(DatevField.CONTRA_ACCOUNT, 8400),
DatevColumn.documentDate(LocalDate.of(2026, 8, 10)),
DatevColumn.of(DatevField.DOCUMENT_FIELD_1, "RE-42"),
DatevColumn.of(DatevField.POSTING_TEXT, "Invoice 42")
);
try (OutputStream output = Files.newOutputStream(
Path.of("EXTF_Buchungsstapel.csv"))) {
file.writeTo(output);
}
}
}
```
Its readable English constants carry the exact German output headings. A misspelled field becomes a compile-time error while the emitted heading remains canonical.
Large exports
## Stream through a buffered destination
DatevStreamWriter writes the management record and heading when it is built, then prepares and hands off one booking row per append without retaining successful rows. Wrap an otherwise unbuffered file or network destination in BufferedOutputStream to reduce small operating-system writes.
```
import io.github.mrtyldr.datev.plain.DatevStreamWriter;
import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
try (OutputStream file = Files.newOutputStream(
Path.of("EXTF_Buchungsstapel.csv"));
OutputStream output = new BufferedOutputStream(file);
DatevStreamWriter writer = DatevStreamWriter.builder()
.metadata(metadata)
.validator(validator)
.build(output)) {
for (Map row : bookingRows) {
writer.append(row);
}
}
```
- The default JDK buffer size is a sound starting point; tune only from measurements.
- Do not add another buffer around ByteArrayOutputStream, StringWriter or an already buffered destination.
- The writer flushes but does not close the caller-owned destination. Declaring it last makes try-with-resources close the writer first, then the buffer and file.
- A validation failure leaves the current output unchanged. An I/O failure can occur after a destination accepted part of a row; physical rollback is impossible, and the writer becomes terminal.
Library-managed working memory follows the row being assembled rather than the total row count. A validator or destination such as ByteArrayOutputStream may still retain data, so choose a genuinely streaming destination when heap use matters.
Legacy contract
## Select v12 deliberately
Use matching v12 metadata and schema. The builder rejects a management-record version that does not match its 124-column heading.
```
import io.github.mrtyldr.datev.core.DatevSchema;
DatevMetadata legacyMetadata = DatevMetadata.bookingBatchV12()
.createdAt(LocalDateTime.now())
.origin("RE")
.exportedBy("my_application")
.advisorNumber(1001)
.clientNumber(1)
.fiscalYearStart(fiscalStart)
.accountLength(4)
.period(periodStart, periodEnd)
.build();
DatevFile legacy = DatevFile.builder(DatevSchema.LEGACY_V12)
.metadata(legacyMetadata)
.build();
```
v12 support is structurally derived from the first 124 v13 fields and covered by library tests. Release 0.2.0 has no independently pinned official v12 fixture and no recorded real-target acceptance result. See the version matrix.
Final step
## Verify beyond the library
### Test your mapping
Assert the approved accounts, tax choices, dates and source-to-field mapping in your application.
### Inspect the file boundary
Keep generated bytes as Windows-1252 with CRLF records; do not let a later UTF-8 text step rewrite them.
### Use DATEV tooling and the real target
Run the applicable checker workflow and a controlled import in the licensed, configured target environment. Record the product/version and result for your own compatibility evidence.
Review claims and limitations Open API 0.2.0
---
Source: https://mrtyldr.github.io/datev-exporter/en/compatibility.html
Evidence statement · release 0.2.0
# Know what is verified—and what remains yours.
Compatibility here means a documented file-format contract with graded test evidence. It does not mean DATEV certification, partnership or guaranteed acceptance by a product installation.
Version matrix
## v13 has pinned official-contract evidence. v12 is structurally derived.
Dimension
v13
Legacy v12
Library schema
implementedCURRENT_V13, exactly 125 booking columns.
implementedLEGACY_V12, exactly 124 booking columns.
Difference
Includes field 125, Abw. Skontokonto.
The exact first 124 fields of the library’s v13 table; field 125 is absent.
EXTF management record
implementedDatevMetadata.bookingBatchV13(), with schema/version mismatch rejected.
implementedDatevMetadata.bookingBatchV12(), with schema/version mismatch rejected.
Built-in complete-file output
implementedManagement record, official heading and booking rows.
implementedManagement record, official heading and booking rows.
Pinned official checker-schema comparison
contract-testedAll 125 field types, lengths, decimal places, required flags and applicable labels/aliases compared with the schema shipped in DATEV Prüfprogramm DATEV-Format 2.2.3.0.
not independentNo separate official v12 checker schema or fixture is pinned in this release.
Official sample contract
contract-testedExact heading compared and all 54 booking rows in the pinned official v13 sample processed by strict semantic validation.
derived onlyLibrary unit tests prove the 124-column prefix, widths and serialization; no independent official v12 sample is tested.
Real target import acceptance
not evidencedNo recorded licensed real-environment acceptance test in this release.
not evidencedNo recorded licensed real-environment acceptance test in this release.
Claim level
Official-contract-tested v13 file generation; still an import candidate.
Derived structural v12 generation; treat as a lower-evidence legacy path.
The opt-in test reads pinned official artifacts and validates generated structure. The supplied checker is an interactive Windows GUI with no documented headless pass/fail exit-code contract. The test does not claim a successful GUI report or downstream product import.
How the claim is built
## The evidence ladder
### Library invariants
Default tests pin the two schema widths, prove v12 is the first 124 fields of v13, enforce version-matched metadata, and exercise Windows-1252/CRLF serialization and the 99,999-row boundary.
### Pinned official v13 artifacts
The opt-in datevCheckerTest downloads the official checker and official sample archives, verifies their fixed SHA-256 values, then compares the in-memory schema and sample content. External copyrighted artifacts are not copied into the repository.
### Generated fixture inspection
A deterministic complete v13 fixture is decoded strictly as Windows-1252 and inspected for its management record, exact unquoted heading, 125-cell booking row and CRLF record boundaries.
### Target acceptance remains open
A licensed operator must inspect the checker report and import into the actual configured target. Client settings, product versions, master data and accounting decisions lie beyond a portable Java test.
Review the versioned official-schema compatibility test and its pinned download/checksum setup.
Exact file boundary
## What complete built-in output guarantees
Property
Contract
Record sequence
EXTF management record, fixed official heading, then zero to 99,999 booking rows.
Delimiter
Semicolon (;).
Line ending
CRLF (\r\n) for every emitted record.
Byte encoding
Strict Windows-1252 on built-in OutputStream paths; unmappable metadata or booking values are rejected rather than replaced.
Heading
Exact fixed v13 or v12 order, emitted unquoted by the built-in writer.
Booking-row quoting
DATEV text-column quoting and CSV escaping through the shared DatevCsv codec.
Atomic validation
Formatting, structural, encoding and configured semantic checks complete before the booking row is handed to the destination. An I/O error cannot be rolled back physically.
A caller-supplied character Writer controls its eventual byte encoding. Metadata-free advanced output may deliberately select a different charset for a custom downstream CSV contract; that is not a complete canonical EXTF byte profile.
Product scope
## Capabilities and explicit non-goals
Area
Status
Meaning
Fixed v13/v12 assembly
yes
Canonical widths/order, typed EXTF metadata and complete built-in file output.
Technical validation
yes
Structure, format, lengths, dependencies and optional metadata-aware account/date/period checks.
Forward-only writing
yes
DatevStreamWriter does not retain successfully written rows; destination buffering remains caller-controlled.
Custom CSV contracts
optional
Advanced can rename/reorder headings; such output is deliberately not compatible with EXTF metadata.
DATEV GUI/server/API integration
no
No authentication, upload, remote API client, desktop automation or server integration.
Accounting or tax logic
no
No debit/credit decision, tax treatment, period close policy or legal advice.
Chart-of-accounts mapping
no
No SKR03/SKR04 or source-system account mapping. The caller supplies approved accounts.
Master-data validation
no
No check that advisers, clients, accounts, tax keys, cost centers or business partners exist in the target.
Import guarantee/certification
no
No promise that a generated file will be accepted by a particular DATEV product or configuration.
Unlimited rows
no
One file is limited to 99,999 booking rows. Split larger exports at an application-approved boundary.
Thread-safe mutable exporters
no
Exporter instances are mutable and not thread-safe; confine each file/writer to one thread.
Primary references
## Sources used for the format contract
- DATEV Developer Portal: technical structure / getting started.
- DATEV Developer Portal: booking-batch format description.
- DATEV Developer Portal: management-record/header description.
- DATEV Developer Portal: character-set description.
- DATEV Developer Portal: Prüfprogramm DATEV-Format and sample data.
Those links describe DATEV’s format. They do not imply affiliation. This site paraphrases only the portions required to state the library contract and does not redistribute DATEV documentation, checker binaries or sample files.
Build an export Choose an API
---
Source: https://mrtyldr.github.io/datev-exporter/en/reference.html
Decision guide · API 0.2.0
# Use the smallest module that owns your contract.
The fixed official format, custom CSV needs and existing Univocity pipelines are separate use cases. Choosing explicitly keeps dependencies and output claims honest.
## Deep-dive references
Four pages cover the parts of the DATEV contract that generate the most questions. Each is generated from the library, so the tables match what the exporters actually write.
### Field reference
All 125 Buchungsstapel columns in output order, with official headings, checker types, lengths and version-12 availability.
### Validation errors
The six stable error codes, what raises each one, the paired fields and the three validation depths.
### EXTF header
The 31-field management record: fixed identifiers, date and timestamp formats, quoting rules and the coded fields.
### Encoding and umlauts
Windows-1252, CRLF, semicolons and quoting — which characters survive and how exports get corrupted afterwards.
Artifacts
## Module map
Artifact
Runtime dependencies
Responsibility
datev-exporter
None (platform POM)
BOM that aligns every module on one version. It contains no runtime API.
datev-exporter-core
None
Canonical schemas, field definitions, metadata, headers, CSV codec and validation model.
datev-exporter-plain
core
Fixed v13/v12 retained file and forward-only writer. Recommended output module.
datev-exporter-field-validator
core
Optional semantic validator callback for the plain exporter.
datev-exporter-advanced
core
Retained files with custom/renamed/reordered headings and built-in validation modes.
datev-exporter-advanced-univocity
advanced + Univocity
Adapter for applications already committed to a Univocity CsvWriter pipeline.
datev-exporter-verification and datev-exporter-benchmarks are internal build modules; they are not in the BOM or Maven Central publication.
Decision table
## Plain, advanced or Univocity?
Need
Plain
Advanced
Univocity adapter
Complete fixed v13/v12 EXTF
recommended
yes with exact official header, strict mode and compatible metadata
no management record
Forward-only rows
yes DatevStreamWriter
no rows retained
Writes advanced retained rows through a third-party writer
Rename/reorder headings
no
yes
yes via advanced file
Custom charset
no byte path is Windows-1252
Only for metadata-free custom downstream contracts
Uses advanced file charset; strict encoder wrapper provided
Third-party runtime dependency
None beyond core
None beyond core
Univocity
Official heading byte shape
Canonical unquoted heading
Canonical on built-in writer with official header
Text headings are quoted differently
Use plain unless you can state a concrete custom-heading requirement. Use retained DatevFile for inspection/replay and DatevStreamWriter for one-pass production.
Layered checks
## Validation catches technical defects, not business truth
Always on in built-in output
### Structural and encoding safety
Column width/order, known headings, CSV syntax/control characters, row limit and strict Windows-1252 encodability on byte output.
Optional plain dependency
### DatevValidator
A format-version/immutable-row callback. Build it with account length, fiscal-year start and period to validate context-dependent account and date rules.
Advanced configuration
### DatevValidationMode
STRICT adds mandatory fields and dependencies; FIELD_LEVEL validates supplied known fields; NONE keeps structural CSV/header checks.
Always application-owned
### Accounting and master data
Account selection, tax treatment, validity in the target ledger and client-specific requirements must be validated outside this library.
Adding datev-exporter-field-validator alone changes nothing. Pass the validator to the plain builder/factory. Official advanced schemas default to STRICT; custom headers default to NONE because their domain semantics are unknown.
Interop, not replacement
## The Univocity adapter solves one narrow problem
Choose datev-exporter-advanced-univocity only when the surrounding application already centralizes CSV emission in Univocity and heading-plus-booking-row output is the intended boundary.
```
CsvWriter writer = DatevUnivocityWriters.newCsvWriter(file, outputStream);
DatevUnivocityWriters.writeTo(file, writer);
```
- A CsvWriter emits uniformly shaped records and therefore cannot emit the differently shaped 31-field EXTF management record.
- writeTo rejects a metadata-backed file. Use the advanced built-in DatevFile.writeTo(OutputStream) for a complete file.
- writeDataTo explicitly writes only heading and rows, even if metadata exists.
- With unmodified official v12/v13 settings, booking rows match built-in output, but text headings are quoted differently. Whole-file byte parity is not claimed.
- The supplied newCsvWriter reports unmappable characters and leaves the caller stream open. Avoid raw Univocity constructors that may replace unsupported characters with ?.
Ownership rules
## Output stays caller-owned
- Built-in writers flush but do not close a caller-supplied OutputStream or Writer.
- Use the OutputStream overload for canonical Windows-1252 bytes. A character Writer is only a character contract; its final encoder is yours.
- Wrap otherwise unbuffered file/network output once. The library intentionally does not choose a persistent buffer size.
- Plain and advanced DatevFile retain accepted rows. DatevStreamWriter hands each accepted row forward and discards its assembly storage.
- All mutable exporter instances are single-threaded by design.
See the buffered streaming example and benchmark report before choosing based on volume.
Symbol-level reference
## Use versioned Javadoc for exact signatures
This guide explains contracts and decisions. The generated API site is the source for public classes, methods and their lifecycle details:
- Javadoc index for release 0.2.0
- Versioned runnable quickstart source
- Published BOM on Maven Central
The project follows Semantic Versioning, but public APIs may change between minor versions until 1.0.0. Pin the BOM version and read release notes when upgrading.
---
Source: https://mrtyldr.github.io/datev-exporter/en/fields.html
Field reference · schema v13 and v12 · 0.2.0
# All 125 Buchungsstapel columns, in official output order.
Field numbers, exact German headings, checker types and lengths for format version 13, with the four differences that matter when you target version 12.
## What this table is
A DATEV Buchungsstapel booking row has a fixed number of columns in a fixed order. Format version 13 defines 125 columns; version 12 defines the first 124 and omits Abw. Skontokonto. Column order carries meaning: a row is positional, so field 7 is Konto whether or not you supplied field 6.
The table below is generated from DatevFieldSpecs, the single canonical copy of the schema that every module in this library derives from. It is not a hand-maintained transcription, so it cannot drift away from what the exporters actually write.
Knowing that field 9 is BU-Schlüssel does not tell you which posting key your case needs. Account mapping, tax treatment and posting logic stay with your application and your tax adviser.
## Shape of the schema
Type
Checker name
Columns
Meaning
TEXT
Text
84
Quoted textual value; the maximum length counts characters.
NUMBER
Zahl
27
Unquoted numeric value with an optional comma decimal separator.
DATE
Datum
7
DATEV-formatted date.
ACCOUNT
Konto
4
Numeric account identifier, narrowed further by the account length.
AMOUNT
Betrag
3
Positive monetary value; the sign lives in Soll/Haben-Kennzeichen.
## The five required fields
Strict validation reports an empty value in these columns as REQUIRED_FIELD. Every other column may be left empty.
#
Official heading
DatevField constant
Type
1
Umsatz (ohne Soll/Haben-Kz)
AMOUNT
Betrag
2
Soll/Haben-Kennzeichen
DEBIT_CREDIT_FLAG
Text
7
Konto
ACCOUNT
Konto
8
Gegenkonto (ohne BU-Schlüssel)
CONTRA_ACCOUNT
Konto
10
Belegdatum
DOCUMENT_DATE
Datum
## Repeating groups and one spelling trap
Two column families repeat as type/content pairs. Supplying one half without the other is reported as DEPENDENT_FIELD_MISSING in strict mode.
- Beleginfo - Art 1 … Beleginfo - Inhalt 8 — eight pairs, fields 21–36.
- Zusatzinformation - Art 1 … Zusatzinformation- Inhalt 20 — twenty pairs, fields 48–87.
DATEV spells the pair inconsistently: Zusatzinformation - Art 1 has spaces around the dash, but Zusatzinformation- Inhalt 1 has none. Both spellings are reproduced exactly. Use the DatevField constants and a typo becomes a compile error instead of a rejected file.
## Full field table
#
Official heading
DatevField constant
Type
Max. length
Decimals
Required
In v12
1
Umsatz (ohne Soll/Haben-Kz)
AMOUNT
Betrag
10
2
yes
yes
2
Soll/Haben-Kennzeichen
DEBIT_CREDIT_FLAG
Text
1
—
yes
yes
3
WKZ Umsatz
CURRENCY
Text
3
—
no
yes
4
Kurs
EXCHANGE_RATE
Zahl
5
6
no
yes
5
Basis-Umsatz
BASE_AMOUNT
Betrag
10
2
no
yes
6
WKZ Basis-Umsatz
BASE_CURRENCY
Text
3
—
no
yes
7
Konto
ACCOUNT
Konto
9
—
yes
yes
8
Gegenkonto (ohne BU-Schlüssel)
CONTRA_ACCOUNT
Konto
9
—
yes
yes
9
BU-Schlüssel
POSTING_KEY
Text
4
—
no
yes
10
Belegdatum
DOCUMENT_DATE
Datum
8
—
yes
yes
11
Belegfeld 1
DOCUMENT_FIELD_1
Text
36
—
no
yes
12
Belegfeld 2
DOCUMENT_FIELD_2
Text
12
—
no
yes
13
Skonto
CASH_DISCOUNT
Betrag
8
2
no
yes
14
Buchungstext
POSTING_TEXT
Text
60
—
no
yes
15
Postensperre
ITEM_BLOCK
Zahl
1
—
no
yes
16
Diverse Adressnummer
MISC_ADDRESS_NUMBER
Text
9
—
no
yes
17
Geschäftspartnerbank
PARTNER_BANK
Zahl
3
—
no
yes
18
Sachverhalt
MATTER_CODE
Zahl
2
—
no
yes
19
Zinssperre
INTEREST_BLOCK
Zahl
1
—
no
yes
20
Beleglink
DOCUMENT_LINK
Text
210
—
no
yes
21
Beleginfo - Art 1
DOCUMENT_INFO_TYPE_1
Text
20
—
no
yes
22
Beleginfo - Inhalt 1
DOCUMENT_INFO_CONTENT_1
Text
210
—
no
yes
23
Beleginfo - Art 2
DOCUMENT_INFO_TYPE_2
Text
20
—
no
yes
24
Beleginfo - Inhalt 2
DOCUMENT_INFO_CONTENT_2
Text
210
—
no
yes
25
Beleginfo - Art 3
DOCUMENT_INFO_TYPE_3
Text
20
—
no
yes
26
Beleginfo - Inhalt 3
DOCUMENT_INFO_CONTENT_3
Text
210
—
no
yes
27
Beleginfo - Art 4
DOCUMENT_INFO_TYPE_4
Text
20
—
no
yes
28
Beleginfo - Inhalt 4
DOCUMENT_INFO_CONTENT_4
Text
210
—
no
yes
29
Beleginfo - Art 5
DOCUMENT_INFO_TYPE_5
Text
20
—
no
yes
30
Beleginfo - Inhalt 5
DOCUMENT_INFO_CONTENT_5
Text
210
—
no
yes
31
Beleginfo - Art 6
DOCUMENT_INFO_TYPE_6
Text
20
—
no
yes
32
Beleginfo - Inhalt 6
DOCUMENT_INFO_CONTENT_6
Text
210
—
no
yes
33
Beleginfo - Art 7
DOCUMENT_INFO_TYPE_7
Text
20
—
no
yes
34
Beleginfo - Inhalt 7
DOCUMENT_INFO_CONTENT_7
Text
210
—
no
yes
35
Beleginfo - Art 8
DOCUMENT_INFO_TYPE_8
Text
20
—
no
yes
36
Beleginfo - Inhalt 8
DOCUMENT_INFO_CONTENT_8
Text
210
—
no
yes
37
KOST1 - Kostenstelle
COST_CENTER_1
Text
36
—
no
yes
38
KOST2 - Kostenstelle
COST_CENTER_2
Text
36
—
no
yes
39
Kost-Menge
COST_QUANTITY
Zahl
12
4
no
yes
40
EU-Land u. UStID (Bestimmung)
EU_COUNTRY_VAT_ID_DESTINATION
Text
15
—
no
yes
41
EU-Steuersatz (Bestimmung)
EU_TAX_RATE_DESTINATION
Zahl
2
2
no
yes
42
Abw. Versteuerungsart
DIFFERING_TAXATION_TYPE
Text
1
—
no
yes
43
Sachverhalt L+L
MATTER_CODE_LL
Zahl
3
—
no
yes
44
Funktionsergänzung L+L
FUNCTION_SUPPLEMENT_LL
Zahl
3
—
no
yes
45
BU 49 Hauptfunktionstyp
BU49_MAIN_FUNCTION_TYPE
Zahl
1
—
no
yes
46
BU 49 Hauptfunktionsnummer
BU49_MAIN_FUNCTION_NUMBER
Zahl
2
—
no
yes
47
BU 49 Funktionsergänzung
BU49_FUNCTION_SUPPLEMENT
Zahl
3
—
no
yes
48
Zusatzinformation - Art 1
ADDITIONAL_INFO_TYPE_1
Text
20
—
no
yes
49
Zusatzinformation- Inhalt 1
ADDITIONAL_INFO_CONTENT_1
Text
210
—
no
yes
50
Zusatzinformation - Art 2
ADDITIONAL_INFO_TYPE_2
Text
20
—
no
yes
51
Zusatzinformation- Inhalt 2
ADDITIONAL_INFO_CONTENT_2
Text
210
—
no
yes
52
Zusatzinformation - Art 3
ADDITIONAL_INFO_TYPE_3
Text
20
—
no
yes
53
Zusatzinformation- Inhalt 3
ADDITIONAL_INFO_CONTENT_3
Text
210
—
no
yes
54
Zusatzinformation - Art 4
ADDITIONAL_INFO_TYPE_4
Text
20
—
no
yes
55
Zusatzinformation- Inhalt 4
ADDITIONAL_INFO_CONTENT_4
Text
210
—
no
yes
56
Zusatzinformation - Art 5
ADDITIONAL_INFO_TYPE_5
Text
20
—
no
yes
57
Zusatzinformation- Inhalt 5
ADDITIONAL_INFO_CONTENT_5
Text
210
—
no
yes
58
Zusatzinformation - Art 6
ADDITIONAL_INFO_TYPE_6
Text
20
—
no
yes
59
Zusatzinformation- Inhalt 6
ADDITIONAL_INFO_CONTENT_6
Text
210
—
no
yes
60
Zusatzinformation - Art 7
ADDITIONAL_INFO_TYPE_7
Text
20
—
no
yes
61
Zusatzinformation- Inhalt 7
ADDITIONAL_INFO_CONTENT_7
Text
210
—
no
yes
62
Zusatzinformation - Art 8
ADDITIONAL_INFO_TYPE_8
Text
20
—
no
yes
63
Zusatzinformation- Inhalt 8
ADDITIONAL_INFO_CONTENT_8
Text
210
—
no
yes
64
Zusatzinformation - Art 9
ADDITIONAL_INFO_TYPE_9
Text
20
—
no
yes
65
Zusatzinformation- Inhalt 9
ADDITIONAL_INFO_CONTENT_9
Text
210
—
no
yes
66
Zusatzinformation - Art 10
ADDITIONAL_INFO_TYPE_10
Text
20
—
no
yes
67
Zusatzinformation- Inhalt 10
ADDITIONAL_INFO_CONTENT_10
Text
210
—
no
yes
68
Zusatzinformation - Art 11
ADDITIONAL_INFO_TYPE_11
Text
20
—
no
yes
69
Zusatzinformation- Inhalt 11
ADDITIONAL_INFO_CONTENT_11
Text
210
—
no
yes
70
Zusatzinformation - Art 12
ADDITIONAL_INFO_TYPE_12
Text
20
—
no
yes
71
Zusatzinformation- Inhalt 12
ADDITIONAL_INFO_CONTENT_12
Text
210
—
no
yes
72
Zusatzinformation - Art 13
ADDITIONAL_INFO_TYPE_13
Text
20
—
no
yes
73
Zusatzinformation- Inhalt 13
ADDITIONAL_INFO_CONTENT_13
Text
210
—
no
yes
74
Zusatzinformation - Art 14
ADDITIONAL_INFO_TYPE_14
Text
20
—
no
yes
75
Zusatzinformation- Inhalt 14
ADDITIONAL_INFO_CONTENT_14
Text
210
—
no
yes
76
Zusatzinformation - Art 15
ADDITIONAL_INFO_TYPE_15
Text
20
—
no
yes
77
Zusatzinformation- Inhalt 15
ADDITIONAL_INFO_CONTENT_15
Text
210
—
no
yes
78
Zusatzinformation - Art 16
ADDITIONAL_INFO_TYPE_16
Text
20
—
no
yes
79
Zusatzinformation- Inhalt 16
ADDITIONAL_INFO_CONTENT_16
Text
210
—
no
yes
80
Zusatzinformation - Art 17
ADDITIONAL_INFO_TYPE_17
Text
20
—
no
yes
81
Zusatzinformation- Inhalt 17
ADDITIONAL_INFO_CONTENT_17
Text
210
—
no
yes
82
Zusatzinformation - Art 18
ADDITIONAL_INFO_TYPE_18
Text
20
—
no
yes
83
Zusatzinformation- Inhalt 18
ADDITIONAL_INFO_CONTENT_18
Text
210
—
no
yes
84
Zusatzinformation - Art 19
ADDITIONAL_INFO_TYPE_19
Text
20
—
no
yes
85
Zusatzinformation- Inhalt 19
ADDITIONAL_INFO_CONTENT_19
Text
210
—
no
yes
86
Zusatzinformation - Art 20
ADDITIONAL_INFO_TYPE_20
Text
20
—
no
yes
87
Zusatzinformation- Inhalt 20
ADDITIONAL_INFO_CONTENT_20
Text
210
—
no
yes
88
Stück
PIECES
Zahl
8
—
no
yes
89
Gewicht
WEIGHT
Zahl
8
2
no
yes
90
Zahlweise
PAYMENT_METHOD
Zahl
2
—
no
yes
91
Forderungsart
RECEIVABLE_TYPE
Text
10
—
no
yes
92
Veranlagungsjahr
ASSESSMENT_YEAR
Zahl
4
—
no
yes
93
Zugeordnete Fälligkeit
ASSIGNED_DUE_DATE
Datum
8
—
no
yes
94
Skontotyp
CASH_DISCOUNT_TYPE
Zahl
1
—
no
yes
95
Auftragsnummer
ORDER_NUMBER
Text
30
—
no
yes
96
Buchungstyp
POSTING_TYPE
Text
2
—
no
yes
97
USt-Schlüssel (Anzahlungen)
VAT_KEY_PREPAYMENT
Zahl
2
—
no
yes
98
EU-Land (Anzahlungen)
EU_COUNTRY_PREPAYMENT
Text
2
—
no
yes
99
Sachverhalt L+L (Anzahlungen)
MATTER_CODE_LL_PREPAYMENT
Zahl
3
—
no
yes
100
EU-Steuersatz (Anzahlungen)
EU_TAX_RATE_PREPAYMENT
Zahl
2
2
no
yes
101
Erlöskonto (Anzahlungen)
REVENUE_ACCOUNT_PREPAYMENT
Konto
9
—
no
yes
102
Herkunft-Kz
ORIGIN_CODE
Text
2
—
no
yes
103
Buchungs GUID
POSTING_GUID
Text
36
—
no
yes
104
KOST-Datum
COST_DATE
Datum
8
—
no
yes
105
SEPA-Mandatsreferenz
SEPA_MANDATE_REFERENCE
Text
35
—
no
yes
106
Skontosperre
CASH_DISCOUNT_BLOCK
Zahl
1
—
no
yes
107
Gesellschaftername
SHAREHOLDER_NAME
Text
76
—
no
yes
108
Beteiligtennummer
PARTICIPANT_NUMBER
Zahl
4
—
no
yes
109
Identifikationsnummer
IDENTIFICATION_NUMBER
Text
11
—
no
yes
110
Zeichnernummer
SUBSCRIBER_NUMBER
Text
20
—
no
yes
111
Postensperre bis
ITEM_BLOCK_UNTIL
Datum
8
—
no
yes
112
Bezeichnung SoBil-Sachverhalt
SOBIL_MATTER_LABEL
Text
30
—
no
yes
113
Kennzeichen SoBil-Buchung
SOBIL_POSTING_FLAG
Zahl
2
—
no
yes
114
Festschreibung
FINAL_POSTING_FLAG
Zahl
1
—
no
yes
115
Leistungsdatum
SERVICE_DATE
Datum
8
—
no
yes
116
Datum Zuord. Steuerperiode
TAX_PERIOD_DATE
Datum
8
—
no
yes
117
Fälligkeit
DUE_DATE
Datum
8
—
no
yes
118
Generalumkehr (GU)
GENERAL_REVERSAL
Text
1
—
no
yes
119
Steuersatz
TAX_RATE
Zahl
2
2
no
yes
120
Land
COUNTRY
Text
2
—
no
yes
121
Abrechnungsreferenz
SETTLEMENT_REFERENCE
Text
50
—
no
yes
122
BVV-Position
BVV_POSITION
Zahl
1
—
no
yes
123
EU-Land u. UStID (Ursprung)
EU_COUNTRY_VAT_ID_ORIGIN
Text
15
—
no
yes
124
EU-Steuersatz (Ursprung)
EU_TAX_RATE_ORIGIN
Zahl
2
2
no
yes
125
Abw. Skontokonto
DIFFERING_CASH_DISCOUNT_ACCOUNT
Konto
8
—
no
no
## Addressing a field from Java
Every DatevColumn factory accepts either the enum constant or the raw heading string, and both produce identical output. The constant is checked at compile time.
```
import io.github.mrtyldr.datev.core.DatevColumn;
import io.github.mrtyldr.datev.core.DatevField;
import io.github.mrtyldr.datev.core.DatevSchema;
// Field 7, "Konto" — compile-checked.
DatevColumn account = DatevColumn.account(DatevField.ACCOUNT, 1000);
// Identical output, but a typo would only surface at runtime.
DatevColumn same = DatevColumn.account("Konto", 1000);
int number = DatevField.ACCOUNT.fieldNumber(); // 7
String heading = DatevField.ACCOUNT.heading(); // "Konto"
boolean inLegacy = DatevField.DIFFERING_CASH_DISCOUNT_ACCOUNT
.isPresentIn(DatevSchema.LEGACY_V12); // false
```
DatevField constants are declared in output order, so ordinal() + 1 is the DATEV field number, and isPresentIn(DatevSchema.LEGACY_V12) answers the version-12 question for any field.
## Related references
- Validation errors — the six error codes explained
- EXTF header — the 31-field management record
- Encoding — Windows-1252, CRLF, quoting and umlauts
---
Source: https://mrtyldr.github.io/datev-exporter/en/validation-errors.html
Validation reference · 0.2.0
# Six error codes, and what each one is telling you.
Validation failures carry a stable machine-readable code, the DATEV field number and the official column name. Here is what triggers each code and what to change.
## Three validation depths
Depth is a deliberate choice per file. A stricter mode never changes the bytes that are written; it only changes what is rejected before writing.
Mode
What it checks
Possible codes
NONE
Nothing semantic. The exporter's structural checks — row width, control characters, encodability — still apply.
—
FIELD_LEVEL
Each supplied non-empty cell against its official field definition.
INVALID_FORMAT, VALUE_OUT_OF_RANGE, TEXT_TOO_LONG, UNMAPPABLE_CHARACTER
STRICT
Everything above, plus required fields and cross-field dependencies.
all six
## The six codes
Code
Raised when
Usual fix
REQUIRED_FIELD
A field the official checker marks as necessary is empty, in strict mode on an official schema.
Populate the field. Only five columns are affected: Umsatz, Soll/Haben-Kennzeichen, Konto, Gegenkonto and Belegdatum.
INVALID_FORMAT
A value does not use DATEV's required representation — a malformed number, a date that is not a real calendar date, a flag outside its allowed set, or a control or line-separator character inside a cell.
Format the value the way DATEV expects rather than the way your locale prints it. Strip newlines and tabs from free text.
VALUE_OUT_OF_RANGE
The value is syntactically valid but exceeds its range — too many integral digits, too many decimals, or an account number wider than the configured account length.
Check the field's maximum length and decimal places in the field reference, and check that the account length in your metadata matches the client.
TEXT_TOO_LONG
A text value exceeds the field's maximum character count.
Truncate deliberately in your own mapping. Silent truncation is not performed for you, because losing part of a Buchungstext is a business decision.
UNMAPPABLE_CHARACTER
The value contains a code point that Windows-1252 cannot represent.
Transliterate or replace the character before export. See the encoding reference for which characters survive.
DEPENDENT_FIELD_MISSING
One half of a paired field group was supplied without the other, in strict mode.
Supply both halves, or neither.
## The paired fields
Strict mode enforces these pairs. Supplying either side alone produces DEPENDENT_FIELD_MISSING on the missing side.
- Basis-Umsatz ↔ WKZ Basis-Umsatz (fields 5 and 6).
- Beleginfo - Art n ↔ Beleginfo - Inhalt n for n = 1…8.
- Zusatzinformation - Art n ↔ Zusatzinformation- Inhalt n for n = 1…20.
## Context sharpens the checks
Some rules cannot be evaluated from the schema alone. A validation context carries the facts that make them decidable; without it, those specific checks are simply skipped rather than guessed.
- Account length narrows how wide Konto and Gegenkonto may be.
- Fiscal year start and posting period let the four-digit Belegdatum be resolved against real calendar dates.
These checks confirm the file matches the technical schema. They say nothing about whether the bookings are correct, or whether a specific DATEV product and configuration will accept the file.
## Reading errors in code
A rejected row raises DatevValidationException, which carries the full list of errors. Each error keeps its code, field number and official column name, so failures can be logged or mapped without parsing message text.
```
import io.github.mrtyldr.datev.core.DatevValidationError;
import io.github.mrtyldr.datev.core.DatevValidationException;
try {
file.append(columns);
} catch (DatevValidationException failure) {
for (DatevValidationError error : failure.errors()) {
log.warn("field {} ({}): {} — {}",
error.fieldNumber(),
error.canonicalKey(),
error.code(),
error.message());
}
}
```
## Related references
- Field reference — all 125 Buchungsstapel columns
- EXTF header — the 31-field management record
- Encoding — Windows-1252, CRLF, quoting and umlauts
---
Source: https://mrtyldr.github.io/datev-exporter/en/extf-header.html
Format reference · EXTF · 0.2.0
# The line before the headings.
A Buchungsstapel file opens with a management record whose shape has nothing to do with the booking rows beneath it. Getting it wrong is the most common reason an otherwise correct export is rejected.
## Three records, two shapes
A complete file is three layers: the EXTF management record, the exact versioned column heading, and the booking rows. Only the last two share a shape. The management record always has 31 fields, whichever format version you target.
The first five fields are fixed identifiers. They are what a reader uses to recognise the file at all:
Field
Value
Meaning
1
EXTF
Identifies an EXTF export file.
2
700
Header version.
3
21
Format category for Buchungsstapel.
4
Buchungsstapel
Format name.
5
13 / 12
Data format version: 13 or 12.
## A real management record
These lines are produced by the library itself, from metadata with a fixed timestamp so the output is reproducible.
Format version 13
```
"EXTF";700;21;"Buchungsstapel";13;20260812093000000;;"RE";"my_application";"";1001;1;20260101;4;20260801;20260831;"August 2026";"";1;0;1;"EUR";;"";;;"";;;"";"my-application"
```
Format version 12 — identical except field 5
```
"EXTF";700;21;"Buchungsstapel";12;20260812093000000;;"RE";"my_application";"";1001;1;20260101;4;20260801;20260831;"August 2026";"";1;0;1;"EUR";;"";;;"";;;"";"my-application"
```
Reserved fields are written as empty cells, and text fields stay quoted even when empty. Dropping a field instead of emptying it shifts every later field by one position.
## Formats that trip people up
- Created-at timestamp uses yyyyMMddHHmmssSSS — 17 digits including milliseconds, unquoted.
- Fiscal year start and posting period use yyyyMMdd, unquoted.
- Text fields are quoted, including designated empty ones. A quote inside application information is escaped by doubling it.
- Numeric fields are unquoted, including the adviser and client numbers.
## The coded fields
Four fields take values from a closed set rather than free input.
Constant
DATEV value
FINANCIAL_ACCOUNTING
1
ANNUAL_FINANCIAL_STATEMENTS
2
Constant
DATEV value
INDEPENDENT
0
TAX_LAW
30
CALCULATION
40
COMMERCIAL_LAW
50
IFRS
64
## Building it from Java
Metadata is built once per file and validated on construction, so an impossible combination fails before any row is written. The builder chooses the format version, and the exporter refuses a management record whose version does not match its heading.
```
import io.github.mrtyldr.datev.core.DatevMetadata;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Currency;
DatevMetadata metadata = DatevMetadata.bookingBatchV13()
.createdAt(LocalDateTime.now())
.origin("RE")
.exportedBy("my_application")
.advisorNumber(1001)
.clientNumber(1)
.fiscalYearStart(LocalDate.of(2026, 1, 1))
.accountLength(4)
.period(LocalDate.of(2026, 8, 1), LocalDate.of(2026, 8, 31))
.description("August 2026")
.currency(Currency.getInstance("EUR"))
.applicationInformation("my-application")
.build();
String record = metadata.toCsvLine(); // the 31-field management record
```
A v12 management record cannot be combined with the 125-column v13 heading. The builder rejects the mismatch rather than writing a file that no importer can interpret.
## Related references
- Field reference — all 125 Buchungsstapel columns
- Validation errors — the six error codes explained
- Encoding — Windows-1252, CRLF, quoting and umlauts
---
Source: https://mrtyldr.github.io/datev-exporter/en/encoding.html
Codec reference · 0.2.0
# Windows-1252 is not a detail you can postpone.
A Buchungsstapel file is bytes, not text. Umlauts survive; a Turkish dotless i does not. One careless UTF-8 step after export undoes everything.
## The byte contract
Property
Value
Character encoding
windows-1252
Record separator
\r\n (CRLF)
Field delimiter
;
Quote character
"
Escaped quote
""
## When a value is quoted
Two independent rules decide quoting, and both are applied.
- Official text columns are always quoted, even when empty. 84 of the 125 version 13 columns are text columns.
- Any other value is quoted only when it must be — that is, when it contains a semicolon or a quote character.
- An embedded quote is doubled, never backslash-escaped.
## Which characters survive
Windows-1252 is a single-byte encoding, so it can represent at most 256 code points. German text is comfortably inside that range; a lot of other text is not.
Encodable — written unchanged
```
ä ö ü ß Ä Ö Ü € § µ ° á é í ó ú ñ ç å ø æ š ž
```
Not encodable — rejected as UNMAPPABLE_CHARACTER
```
ı ğ ş ł ą č ř ő ū 日 😀
```
A value containing an unencodable character is refused rather than silently replaced with a question mark, because a corrupted Buchungstext is harder to notice later than a failed export now. Transliterate deliberately in your own mapping if your source data can contain such characters.
## Control characters
Control, line-separator and paragraph-separator characters are rejected anywhere in a cell, reported as INVALID_FORMAT. A newline inside a Buchungstext would otherwise split one booking row into two unusable records.
## How exports get corrupted after they are written
The library controls the bytes it writes. Everything downstream of that is yours to protect.
- A text editor that opens the file and saves it back as UTF-8 — every umlaut becomes two bytes and the file is no longer valid.
- A transfer or archiving step configured for text mode that rewrites CRLF to LF.
- Reading the file back with the platform default charset instead of Windows-1252.
- A templating or logging layer that normalises the output to Unicode NFD, splitting umlauts into base letter plus combining mark.
A file that looks right in an editor may already be broken. Check the byte length and the encoding, and keep the generated file untouched between export and import.
## Related references
- Field reference — all 125 Buchungsstapel columns
- Validation errors — the six error codes explained
- EXTF header — the 31-field management record
---
Source: https://mrtyldr.github.io/datev-exporter/en/benchmarks.html
Measured locally · v0.2.0 · Java 17
# A complete 99,999-row EXTF file.
A reproducible JMH run compares three strictly validated exporter paths, records cumulative allocation, and preserves the uncertainty instead of turning one laptop run into a universal claim.
Observed data
## This run did not resolve a timing difference between the two plain paths.
One operation creates a complete EXTF v13 file containing the management record, the 125-column heading and 99,999 booking rows. Lower is better in the time and allocation columns. The ± values are JMH 99.9% confidence-interval half-widths across ten measurement samples, under JMH’s normality assumption.
Exporter path
Time / file
Derived time / row
Derived rows / second
Allocated bytes / file
Derived allocated bytes / row
Plain forward-onlyDatevStreamWriter
670.193 ± 34.910 ms
6.702 µs
149,209
980,975,803 ± 10,710,036 B
9,809.86 B
Plain retainedDatevFile
670.000 ± 15.068 ms
6.700 µs
149,252
1,011,067,254 ± 10,710,046 B
10,110.77 B
Advanced retainedadvanced.DatevFile
742.976 ± 51.878 ms
7.430 µs
134,593
966,056,224 ± 10,710,041 B
9,660.66 B
The two plain means differ by only 0.03%, far below their reported uncertainty, so this run supports no timing ranking between them. Forward-only allocated about 3.0% fewer cumulative bytes than plain retained in this workload. Advanced retained had the lowest allocation score and the highest observed mean time, but this single run is not evidence of a universal ranking.
Product decision
## Choose the lifecycle first, not the smallest benchmark number.
### Use forward-only for one-pass, high-volume export
DatevStreamWriter validates, serializes and hands off each completed row without retaining it in a library-owned collection. Its live retained row state is therefore proportional to one row rather than the total row count. That design property—not a speed claim—is the strongest reason to prefer it for a 99,999-row one-pass export.
### Use retained output when rows must remain available
The retained APIs support inspection, iteration and delayed writing. That lifecycle is useful when the caller must review or replay rows; this run did not resolve a timing difference versus forward-only. It necessarily keeps aligned rows alive until the file object can be released.
### Allocation is not retained heap
JMH’s gc.alloc.rate.norm reports all bytes allocated during an operation, including short-lived validation and serialization objects. It does not report peak live heap. The advanced retained result demonstrates the distinction: it allocated the fewest cumulative bytes here even though it still retains the aligned rows. A separate live-set or heap-occupancy study would be required to quantify peak memory.
What was measured
## A sparse but non-trivial fixed row.
- Format: complete DATEV Buchungsstapel / EXTF v13, Windows-1252 and CRLF.
- Size: 125 columns; 99,999 booking rows, the supported per-file maximum.
- Density: six non-empty fields per row: amount, debit/credit marker, account, contra account, document date and booking text.
- Escaping: booking text is Müller; Beleg "42" €, exercising Windows-1252, delimiter and quote escaping.
- Validation: metadata-aware strict semantic validation on every append. Plain paths use DatevValidator; advanced uses built-in STRICT mode.
- Output: all paths are checked byte-for-byte and emit exactly 33,602,459 bytes: 2,795 fixed management/heading bytes plus 336 bytes per booking row.
The same immutable six-entry map is submitted for each row. Row alignment, validation and serialization remain inside the timed operation; upstream record creation and accounting-data mapping do not.
Measurement contract
## Environment and JMH configuration.
Library under test
v0.2.0 · commit 06fa7ae
Measured
12 August 2026
Machine
Apple M1 Pro, 10 logical CPUs, 32 GiB RAM, aarch64
Operating system
macOS 26.5.2 (build 25F84)
JVM
Eclipse Temurin 17.0.19+10; -Xms1g -Xmx1g -XX:+AlwaysPreTouch
Harness
JMH 1.37, average-time mode, one thread, two forks
Iterations
Per fork: three × 1 s warmup, then five × 1 s measurement
Profiler
JMH gc; normalized allocation in bytes per operation
Destination
A pre-sized, reusable ByteArrayOutputStream, reset outside each measured invocation
I/O
Byte serialization and destination writes included; filesystem, network and destination allocation excluded
Each measured call constructs its exporter and performs all 99,999 appends plus final output. Immutable fixture construction, output capacity allocation and initial byte-equivalence checks happen at trial setup. The final invocation is checked again at trial teardown.
Run it yourself
## The maximum-row task pins the important inputs.
```
git clone https://github.com/mrtyldr/datev-exporter.git
cd datev-exporter
git checkout cb91f5dd8b174bb4e10d98a8a7cc93f007483042
./gradlew --no-daemon :datev-exporter-benchmarks:jmhMaxRows
```
The task selects the Adoptium Java 17 toolchain and expands to the following JMH settings:
```
-p rowCount=99999
-wi 3 -w 1s
-i 5 -r 1s
-f 2 -t 1
-jvmArgs "-Xms1g -Xmx1g -XX:+AlwaysPreTouch"
-prof gc -rf json
```
Generated JSON is written to datev-exporter-benchmarks/build/results/jmh/max-rows-gc.json. The published summary retains every raw timing and allocation sample:
- Machine-readable result and raw samples
- Benchmark source
- Versioned Java API
Do not over-generalize
## What this run cannot establish.
- It is one run on one developer laptop, without dedicated-host isolation, CPU pinning or thermal controls.
- The ten samples estimate steady-state behavior for this fixture; they are not production latency percentiles.
- Derived rows/second is arithmetic from average file time, not a multi-threaded throughput test.
- The sparse fixed row does not model every field density, value length, validation failure or upstream object-allocation pattern.
- The in-memory destination excludes filesystem, network, encryption, compression and caller-selected buffering costs.
- The profiler measures cumulative allocation, not maximum RSS, peak live heap or retained object size.
- No Univocity path is included: the adapter has a different output boundary and cannot produce the complete management-record-plus-bookings file measured here.
Use these figures to understand this implementation and to reproduce a comparison on your deployment hardware—not as an SLA. Review the compatibility evidence and limits separately; speed does not prove DATEV import acceptance.
---
Source: https://mrtyldr.github.io/datev-exporter/de/
Java 17 · Apache-2.0 · Release 0.2.0
# Buchungsdaten besitzen. Formatschicht wiederverwenden.
Bereits zugeordnete Buchungsdaten werden zu deterministischen DATEV-Buchungsstapel-/EXTF-Dateien – mit festen v13/v12-Schemata, typisierten Metadaten, technischer Validierung und Forward-only-Streaming.
Der Vertrag
## Formatexporter, keine Buchhaltungslogik.
Die Anwendung liefert zugeordnete Konten, Beträge, Daten und fachliche Entscheidungen. Die Bibliothek liefert den EXTF-Verwaltungssatz, die offizielle Spaltenreihenfolge, CSV-Kodierung und deterministische technische Prüfungen.
Exakte Grenzen nachlesen →
Warum es die Bibliothek gibt
## Die Schwierigkeit ist nicht, Werte mit Semikolons zu verbinden.
Ein vollständiger Buchungsstapel kombiniert einen anders aufgebauten Verwaltungssatz, eine exakte versionsgebundene Überschrift und streng formatierte Buchungszeilen. Schon kleine Abweichungen bei Breite, Reihenfolge, Maskierung, Zeilenenden oder Kodierung können einen ansonsten gültigen Export unbrauchbar machen.
### Schema kanonisch halten
Eine geordnete Definition für alle 125 v13-Felder und die 124 Felder der älteren v12-Struktur verwenden – statt eigene Tabellen oder Arrays zu pflegen.
### Vor der Byte-Abweichung scheitern
Strukturelle, Windows-1252- und optionale semantische Verstöße ablehnen, bevor eine Buchungszeile an das Ziel übergeben wird.
### Speichermodell auswählen
Zeilen behalten, wenn sie geprüft oder erneut ausgegeben werden müssen; sie einmalig vorwärts streamen, wenn das Exportvolumen keine Speicherung rechtfertigt.
Lieferumfang
## Eine schmale API für einen präzisen Ausgabevertrag.
Der Standardpfad bleibt abhängigkeitsarm. Optionale Module sind explizit – eine Univocity-Abhängigkeit oder der semantische Validator kommt nur hinzu, wenn er gewählt wird.
Empfohlener Standard
### Plain-Exporter mit festem Schema
Vollständige v13/v12-EXTF-Ausgabe, speichernde DatevFile und der Forward-only-DatevStreamWriter. Die richtige Wahl, solange der Empfängervertrag nicht bewusst von der offiziellen Überschrift abweicht.
Mit Plain beginnen →
Individuelles Folgeformat
### Advanced-Exporter
Überschriften umbenennen, umordnen oder ersetzen und den Validierungsmodus je Datei wählen. Individuelle Überschriften sind nicht mit EXTF-Metadaten kombinierbar, weil sie nicht mehr dem festen DATEV-Schema entsprechen.
Exporter vergleichen →
Nur für vorhandene Pipeline
### Univocity-Adapter
Überschrift und Buchungszeilen über einen vorhandenen Univocity-CsvWriter ausgeben. Er kann den anders geformten Verwaltungssatz nicht erzeugen und maskiert offizielle Textüberschriften abweichend.
Grenze verstehen →
Bewusste Abgrenzung
## Fachliche Daten hinein. Importkandidat heraus.
### In der Anwendung zuordnen
Kontenrahmen, Steuerbehandlung, Stammdaten und mandantenspezifische Regeln vor dem Aufruf des Exporters bestimmen.
### Zusammenstellen und prüfen
Typisierte Metadaten anhängen, benannte oder typisierte Spalten schreiben und metadatenbezogene technische Validierung auswählen.
### Im Zielsystem verifizieren
Die erzeugte Datei über den kontrollierten Übertragungsweg bewegen und die Annahme in der lizenzierten, konfigurierten DATEV-Zielumgebung prüfen.
Eine bestandene Bibliotheksvalidierung – oder die Übereinstimmung mit dem geprüften v13-Schema- und Beispielvertrag – beweist weder die buchhalterische Richtigkeit noch die Annahme durch ein bestimmtes DATEV-Produkt, einen Mandanten oder dessen Konfiguration.
Nachweise statt Adjektive
## Kompatibilitätsaussagen sind abgestuft.
Für v13 fixiert ein optionaler Vertragstest das offizielle DATEV-Prüfprogrammschema und das offizielle Beispielarchiv, vergleicht die 125 Felddefinitionen und validiert alle 54 Beispielbuchungen. Er macht aus dem Start einer Windows-GUI kein bestandenes oder fehlgeschlagenes Importergebnis.
Für v12 unterstützt die Bibliothek das Präfix mit 124 Spalten und den passenden Verwaltungssatz. Aktuell fehlt jedoch ein unabhängiges offizielles v12-Testobjekt oder ein dokumentierter realer Importnachweis.
Kompatibilitätsmatrix öffnen
Weiterlesen
### Nachweise auf der richtigen Ebene nutzen
- Vollständiges v13-Beispiel
- v12/v13-Nachweismatrix
- Validierungsebenen
- Reproduzierbare Benchmarks
- Versionierte Java-API
---
Source: https://mrtyldr.github.io/datev-exporter/de/getting-started.html
Erste Schritte · 0.2.0
# Von zugeordneten Buchungen zur vollständigen EXTF-Datei.
Mit dem Plain-Exporter für feste Schemata beginnen. Typisierte Metadaten und kontextbezogene Validierung ergänzen, dann je nach Lebenszyklus zwischen Speicherung und Forward-only-Ausgabe wählen.
Schritt 0
## Voraussetzungen und Modulauswahl
- Java 17 oder neuer.
- datev-exporter-plain für feste v13/v12-Schemata und Ausgabe.
- datev-exporter-field-validator, wenn deterministische semantische Prüfungen vor der Annahme jeder Zeile ausgeführt werden sollen.
Das Root-Artefakt datev-exporter ist eine Bill of Materials (BOM), kein Runtime-JAR. Es richtet die Modulversionen aus; anschließend werden nur die tatsächlich verwendeten Module eingebunden.
Die Beispiele verwenden Platzhalter für Berater-/Mandantennummern und Kontenzuordnungen. Alle fachlichen Werte müssen durch für das Zielsystem freigegebene Daten ersetzt werden; die Bibliothek ordnet weder SKR03/SKR04 zu noch bestimmt sie die Steuerbehandlung.
Schritt 1A
## Mit Gradle ausführen
Eine Java-Anwendung anlegen, das Java-Beispiel unten als src/main/java/Example.java speichern und dieses build.gradle verwenden:
```
plugins {
id 'application'
}
repositories {
mavenCentral()
}
dependencies {
implementation platform('io.github.mrtyldr:datev-exporter:0.2.0')
implementation 'io.github.mrtyldr:datev-exporter-plain'
implementation 'io.github.mrtyldr:datev-exporter-field-validator'
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
application {
mainClass = 'Example'
}
```
Mit dem Gradle Wrapper starten:
```
./gradlew run
```
Das Repository enthält außerdem eine deterministische, durch CI ausgeführte Anwendung:
```
git clone https://github.com/mrtyldr/datev-exporter.git
cd datev-exporter
./gradlew :examples:quickstart-gradle:run
```
Schritt 1B
## Mit Maven bauen
Dieselbe Example.java funktioniert mit diesem minimalen pom.xml. Die BOM verwaltet die Modulversionen:
```
4.0.0
example
datev-quickstart
1.0.0
17
UTF-8
io.github.mrtyldr
datev-exporter
0.2.0
pom
import
io.github.mrtyldr
datev-exporter-plain
io.github.mrtyldr
datev-exporter-field-validator
org.apache.maven.plugins
maven-compiler-plugin
3.15.0
org.codehaus.mojo
exec-maven-plugin
3.6.3
Example
```
Kompilieren und ausführen:
```
mvn verify exec:java
```
Schritt 2
## Vollständige v13-Datei erstellen
Diese Anwendung schreibt alle drei notwendigen Satzebenen: EXTF-Verwaltungssatz, die exakte v13-Überschrift mit 125 Spalten und eine Buchungszeile. DatevFile behält angenommene Zeilen, damit sie geprüft oder erneut ausgegeben werden können.
```
import io.github.mrtyldr.datev.core.DatevColumn;
import io.github.mrtyldr.datev.core.DatevField;
import io.github.mrtyldr.datev.core.DatevMetadata;
import io.github.mrtyldr.datev.core.DatevValidationContext;
import io.github.mrtyldr.datev.plain.DatevFile;
import io.github.mrtyldr.datev.validation.DatevValidator;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.time.LocalDateTime;
public final class Example {
public static void main(String[] args) throws Exception {
LocalDate fiscalStart = LocalDate.of(2026, 1, 1);
LocalDate periodStart = LocalDate.of(2026, 8, 1);
LocalDate periodEnd = LocalDate.of(2026, 8, 31);
DatevMetadata metadata = DatevMetadata.bookingBatchV13()
.createdAt(LocalDateTime.now())
.origin("RE")
.exportedBy("my_application")
.advisorNumber(1001)
.clientNumber(1)
.fiscalYearStart(fiscalStart)
.accountLength(4)
.period(periodStart, periodEnd)
.description("August 2026")
.applicationInformation("my-application")
.build();
DatevValidationContext context = DatevValidationContext.builder()
.accountLength(metadata.accountLength())
.fiscalYearStart(metadata.fiscalYearStart())
.period(metadata.periodStart(), metadata.periodEnd())
.build();
DatevValidator validator = DatevValidator.builder()
.context(context)
.build();
DatevFile file = DatevFile.builder()
.metadata(metadata)
.validator(validator)
.build();
file.append(
DatevColumn.amount(DatevField.AMOUNT,
new BigDecimal("1250.00")),
DatevColumn.of(DatevField.DEBIT_CREDIT_FLAG, "S"),
DatevColumn.of(DatevField.CURRENCY, "EUR"),
DatevColumn.account(DatevField.ACCOUNT, 1000),
DatevColumn.account(DatevField.CONTRA_ACCOUNT, 8400),
DatevColumn.documentDate(LocalDate.of(2026, 8, 10)),
DatevColumn.of(DatevField.DOCUMENT_FIELD_1, "RE-42"),
DatevColumn.of(DatevField.POSTING_TEXT, "Rechnung 42")
);
try (OutputStream output = Files.newOutputStream(
Path.of("EXTF_Buchungsstapel.csv"))) {
file.writeTo(output);
}
}
}
```
Lesbare englische Konstanten tragen die exakten deutschen Ausgabeüberschriften. Ein falsch geschriebener Feldname wird zum Kompilierfehler, während die Ausgabe kanonisch bleibt.
Große Exporte
## Über ein gepuffertes Ziel streamen
DatevStreamWriter schreibt beim Erstellen Verwaltungssatz und Überschrift. Danach wird je append genau eine Buchungszeile vorbereitet und übergeben, ohne erfolgreiche Zeilen zu behalten. Ein ansonsten ungepuffertes Datei- oder Netzwerkziel in BufferedOutputStream einbetten, um kleine Betriebssystem-Schreibvorgänge zusammenzufassen.
```
import io.github.mrtyldr.datev.plain.DatevStreamWriter;
import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
try (OutputStream file = Files.newOutputStream(
Path.of("EXTF_Buchungsstapel.csv"));
OutputStream output = new BufferedOutputStream(file);
DatevStreamWriter writer = DatevStreamWriter.builder()
.metadata(metadata)
.validator(validator)
.build(output)) {
for (Map row : bookingRows) {
writer.append(row);
}
}
```
- Die JDK-Standardpuffergröße ist ein sinnvoller Ausgangspunkt; Anpassungen nur auf Basis von Messungen.
- Keinen zusätzlichen Puffer um ByteArrayOutputStream, StringWriter oder ein bereits gepuffertes Ziel legen.
- Der Writer leert den Puffer, schließt aber das vom Aufrufer verwaltete Ziel nicht. Durch die letzte Deklaration wird zuerst der Writer und danach Puffer und Datei geschlossen.
- Ein Validierungsfehler verändert die bestehende Ausgabe nicht. Ein E/A-Fehler kann auftreten, nachdem das Ziel einen Teil der Zeile angenommen hat; ein physisches Rollback ist unmöglich und der Writer wird terminal.
Der von der Bibliothek verwaltete Arbeitsspeicher folgt der gerade zusammengesetzten Zeile, nicht der Gesamtzahl. Validator oder Ziel – etwa ByteArrayOutputStream – können Daten trotzdem behalten. Für begrenzten Heap ist daher ein tatsächlich streamendes Ziel nötig.
Älterer Vertrag
## v12 bewusst auswählen
Passende v12-Metadaten und das v12-Schema verwenden. Der Builder lehnt einen Verwaltungssatz ab, dessen Version nicht zur Überschrift mit 124 Spalten passt.
```
import io.github.mrtyldr.datev.core.DatevSchema;
DatevMetadata legacyMetadata = DatevMetadata.bookingBatchV12()
.createdAt(LocalDateTime.now())
.origin("RE")
.exportedBy("my_application")
.advisorNumber(1001)
.clientNumber(1)
.fiscalYearStart(fiscalStart)
.accountLength(4)
.period(periodStart, periodEnd)
.build();
DatevFile legacy = DatevFile.builder(DatevSchema.LEGACY_V12)
.metadata(legacyMetadata)
.build();
```
v12 wird strukturell aus den ersten 124 v13-Feldern abgeleitet und durch Bibliothekstests abgedeckt. Release 0.2.0 besitzt weder ein unabhängig fixiertes offizielles v12-Testobjekt noch ein dokumentiertes Annahmeergebnis aus einem realen Zielsystem. Siehe Versionsmatrix.
Letzter Schritt
## Über die Bibliothek hinaus prüfen
### Zuordnung testen
Freigegebene Konten, Steuerentscheidungen, Daten und Quellfeldzuordnungen in der Anwendung absichern.
### Dateigrenze kontrollieren
Erzeugte Bytes als Windows-1252 mit CRLF-Sätzen erhalten; kein späterer UTF-8-Textschritt darf sie umschreiben.
### DATEV-Werkzeuge und reales Ziel nutzen
Den passenden Prüfablauf und einen kontrollierten Import in der lizenzierten, konfigurierten Zielumgebung durchführen. Produkt/Version und Ergebnis als eigene Kompatibilitätsnachweise dokumentieren.
Aussagen und Grenzen prüfen API 0.2.0 öffnen
---
Source: https://mrtyldr.github.io/datev-exporter/de/compatibility.html
Nachweisstand · Release 0.2.0
# Wissen, was geprüft ist – und was in eigener Verantwortung bleibt.
Kompatibilität bezeichnet hier einen dokumentierten Dateiformatvertrag mit abgestuften Testnachweisen. Sie bedeutet keine DATEV-Zertifizierung, Partnerschaft oder garantierte Annahme durch eine Produktinstallation.
Versionsmatrix
## v13 besitzt fixierte offizielle Vertragsnachweise. v12 ist strukturell abgeleitet.
Dimension
v13
Ältere v12
Bibliotheksschema
implementiertCURRENT_V13, exakt 125 Buchungsspalten.
implementiertLEGACY_V12, exakt 124 Buchungsspalten.
Unterschied
Enthält Feld 125, Abw. Skontokonto.
Exakt die ersten 124 Felder der bibliotheksinternen v13-Tabelle; Feld 125 fehlt.
EXTF-Verwaltungssatz
implementiertDatevMetadata.bookingBatchV13(); unpassende Schema-/Metadatenversion wird abgelehnt.
implementiertDatevMetadata.bookingBatchV12(); unpassende Schema-/Metadatenversion wird abgelehnt.
Vollständige integrierte Ausgabe
implementiertVerwaltungssatz, offizielle Überschrift und Buchungszeilen.
implementiertVerwaltungssatz, offizielle Überschrift und Buchungszeilen.
Fixierter Vergleich mit offiziellem Prüfprogrammschema
vertraglich getestetAlle 125 Feldtypen, Längen, Dezimalstellen, Pflichtkennzeichen sowie relevante Bezeichnungen/Aliase werden mit dem Schema aus Prüfprogramm DATEV-Format 2.2.3.0 verglichen.
nicht unabhängigIn diesem Release ist kein separates offizielles v12-Prüfschema oder -Testobjekt fixiert.
Offizieller Beispielvertrag
vertraglich getestetExakte Überschrift verglichen und alle 54 Buchungszeilen des fixierten offiziellen v13-Beispiels durch strikte semantische Validierung verarbeitet.
nur abgeleitetBibliothekstests belegen Präfix, Breite und Serialisierung mit 124 Spalten; kein unabhängiges offizielles v12-Beispiel wird getestet.
Annahme im realen Zielsystem
nicht belegtKein dokumentierter Annahmetest in einer lizenzierten realen Umgebung für dieses Release.
nicht belegtKein dokumentierter Annahmetest in einer lizenzierten realen Umgebung für dieses Release.
Aussagestufe
Gegen den offiziellen Vertrag getestete v13-Dateierzeugung; weiterhin ein Importkandidat.
Strukturell abgeleitete v12-Dateierzeugung; als älteren Pfad mit niedrigerem Nachweisniveau behandeln.
Der optionale Test liest fixierte offizielle Artefakte und prüft die erzeugte Struktur. Das bereitgestellte Prüfprogramm ist eine interaktive Windows-GUI ohne dokumentierten Headless-Vertrag für Ergebnis oder Exit-Code. Der Test behauptet weder einen erfolgreichen GUI-Bericht noch einen Produktimport.
Aufbau der Aussage
## Die Nachweisleiter
### Bibliotheksinvarianten
Standardtests fixieren beide Schemabreiten, beweisen v12 als die ersten 124 Felder von v13, erzwingen passende Metadatenversionen und testen Windows-1252-/CRLF-Serialisierung sowie die Grenze von 99.999 Zeilen.
### Fixierte offizielle v13-Artefakte
Der optionale datevCheckerTest lädt das offizielle Prüfprogramm- und Beispielarchiv, verifiziert festgelegte SHA-256-Werte und vergleicht anschließend In-Memory-Schema und Beispielinhalt. Externe urheberrechtlich geschützte Artefakte werden nicht ins Repository kopiert.
### Prüfung eines erzeugten Testobjekts
Eine deterministische vollständige v13-Datei wird strikt als Windows-1252 dekodiert und auf Verwaltungssatz, exakte nicht maskierte Überschrift, Buchungszeile mit 125 Zellen und CRLF-Satzgrenzen geprüft.
### Zielannahme bleibt offen
Eine lizenzierte Bedienperson muss den Prüfbericht kontrollieren und in das tatsächlich konfigurierte Ziel importieren. Mandanteneinstellungen, Produktversionen, Stammdaten und Buchungsentscheidungen liegen außerhalb eines portablen Java-Tests.
Einsehbar sind der versionierte Kompatibilitätstest zum offiziellen Schema und die fixierte Download-/Prüfsummenkonfiguration.
Exakte Dateigrenze
## Was die vollständige integrierte Ausgabe zusichert
Eigenschaft
Vertrag
Satzfolge
EXTF-Verwaltungssatz, feste offizielle Überschrift, danach null bis 99.999 Buchungszeilen.
Trennzeichen
Semikolon (;).
Zeilenende
CRLF (\r\n) für jeden ausgegebenen Satz.
Byte-Kodierung
Striktes Windows-1252 auf integrierten OutputStream-Pfaden; nicht darstellbare Metadaten oder Buchungswerte werden abgelehnt, nicht ersetzt.
Überschrift
Exakte feste v13- oder v12-Reihenfolge, durch den integrierten Writer unmaskiert ausgegeben.
Maskierung der Buchungszeile
DATEV-Textspaltenmaskierung und CSV-Escaping über den gemeinsamen DatevCsv-Codec.
Atomare Validierung
Formatierung, Struktur-, Kodierungs- und konfigurierte semantische Prüfungen enden, bevor die Buchungszeile an das Ziel übergeben wird. Ein E/A-Fehler kann physisch nicht zurückgerollt werden.
Ein vom Aufrufer gelieferter Zeichen-Writer kontrolliert seine spätere Byte-Kodierung. Eine metadatenfreie Advanced-Ausgabe darf bewusst einen anderen Zeichensatz für einen individuellen CSV-Folgevertrag wählen; das ist kein vollständiges kanonisches EXTF-Byteprofil.
Produktumfang
## Fähigkeiten und explizite Nicht-Ziele
Bereich
Status
Bedeutung
Feste v13/v12-Erzeugung
ja
Kanonische Breite/Reihenfolge, typisierte EXTF-Metadaten und vollständige integrierte Dateiausgabe.
Technische Validierung
ja
Struktur, Format, Längen, Abhängigkeiten sowie optionale kontextbezogene Konto-/Datums-/Periodenprüfungen.
Forward-only-Ausgabe
ja
DatevStreamWriter behält erfolgreich geschriebene Zeilen nicht; Zielpufferung bleibt beim Aufrufer.
Individuelle CSV-Verträge
optional
Advanced kann Überschriften umbenennen/umordnen; diese Ausgabe ist bewusst nicht mit EXTF-Metadaten kombinierbar.
DATEV-GUI-/Server-/API-Integration
nein
Keine Authentifizierung, Uploads, Remote-API-Clients, Desktop-Automation oder Serverintegration.
Buchhaltungs- oder Steuerlogik
nein
Keine Soll-/Haben-Entscheidung, Steuerbehandlung, Periodenabschlusspolitik oder Rechtsberatung.
Kontenrahmenzuordnung
nein
Keine SKR03-/SKR04- oder Quellsystemkontenzuordnung. Der Aufrufer liefert freigegebene Konten.
Stammdatenprüfung
nein
Keine Prüfung, ob Berater, Mandanten, Konten, Steuerschlüssel, Kostenstellen oder Geschäftspartner im Ziel existieren.
Importgarantie/Zertifizierung
nein
Keine Zusage, dass eine erzeugte Datei von einem bestimmten DATEV-Produkt oder einer Konfiguration angenommen wird.
Unbegrenzte Zeilen
nein
Eine Datei ist auf 99.999 Buchungszeilen begrenzt. Größere Exporte an einer fachlich freigegebenen Grenze aufteilen.
Thread-sichere mutable Exporter
nein
Exporter-Instanzen sind mutabel und nicht thread-sicher; jede Datei/jeden Writer auf einen Thread begrenzen.
Primärreferenzen
## Quellen des Formatvertrags
- DATEV Developer Portal: technischer Aufbau / Einstieg.
- DATEV Developer Portal: Formatbeschreibung Buchungsstapel.
- DATEV Developer Portal: Beschreibung des Verwaltungssatzes.
- DATEV Developer Portal: Zeichensatzbeschreibung.
- DATEV Developer Portal: Prüfprogramm DATEV-Format und Beispieldaten.
Diese Links beschreiben das DATEV-Format; sie implizieren keine Verbindung. Die Website paraphrasiert nur die für den Bibliotheksvertrag nötigen Teile und verteilt weder DATEV-Dokumentation noch Prüfprogrammbinärdateien oder Beispieldateien.
Export erstellen API auswählen
---
Source: https://mrtyldr.github.io/datev-exporter/de/reference.html
Entscheidungshilfe · API 0.2.0
# Das kleinste Modul verwenden, das den eigenen Vertrag erfüllt.
Das feste offizielle Format, individuelle CSV-Anforderungen und vorhandene Univocity-Pipelines sind unterschiedliche Anwendungsfälle. Eine bewusste Auswahl hält Abhängigkeiten und Ausgabeaussagen nachvollziehbar.
## Vertiefende Referenzen
Vier Seiten behandeln die Teile des DATEV-Vertrags, die die meisten Fragen auslösen. Jede wird aus der Bibliothek erzeugt, sodass die Tabellen zu dem passen, was die Exporter tatsächlich schreiben.
### Feldreferenz
Alle 125 Buchungsstapel-Spalten in Ausgabereihenfolge, mit amtlichen Überschriften, Prüfprogramm-Typen, Längen und Verfügbarkeit in Version 12.
### Validierungsfehler
Die sechs stabilen Fehlercodes, ihre Auslöser, die Feldpaare und die drei Prüftiefen.
### EXTF-Header
Der Verwaltungssatz mit 31 Feldern: feste Kennungen, Datums- und Zeitformate, Quoting-Regeln und die kodierten Felder.
### Kodierung und Umlaute
Windows-1252, CRLF, Semikolon und Quoting — welche Zeichen überstehen und wie Exporte nachträglich beschädigt werden.
Artefakte
## Modulübersicht
Artefakt
Runtime-Abhängigkeiten
Verantwortung
datev-exporter
Keine (Plattform-POM)
BOM zur Ausrichtung aller Module auf eine Version. Enthält keine Runtime-API.
datev-exporter-core
Keine
Kanonische Schemata, Felddefinitionen, Metadaten, Überschriften, CSV-Codec und Validierungsmodell.
datev-exporter-plain
core
Feste v13/v12-Datei mit Speicherung und Forward-only-Writer. Empfohlenes Ausgabemodul.
datev-exporter-field-validator
core
Optionaler semantischer Validator-Callback für den Plain-Exporter.
datev-exporter-advanced
core
Speichernde Dateien mit individuellen/umbenannten/umgeordneten Überschriften und integrierten Validierungsmodi.
datev-exporter-advanced-univocity
advanced + Univocity
Adapter für Anwendungen mit bereits festgelegter Univocity-CsvWriter-Pipeline.
datev-exporter-verification und datev-exporter-benchmarks sind interne Build-Module; sie gehören weder zur BOM noch zur Maven-Central-Veröffentlichung.
Entscheidungstabelle
## Plain, Advanced oder Univocity?
Bedarf
Plain
Advanced
Univocity-Adapter
Vollständige feste v13/v12-EXTF
empfohlen
ja mit exakter offizieller Überschrift, Strict-Modus und passenden Metadaten
kein Verwaltungssatz
Forward-only-Zeilen
ja DatevStreamWriter
nein Zeilen werden behalten
Schreibt gespeicherte Advanced-Zeilen über Drittanbieter-Writer
Überschriften umbenennen/-ordnen
nein
ja
ja über Advanced-Datei
Eigener Zeichensatz
nein Byte-Pfad ist Windows-1252
Nur für metadatenfreie individuelle Folgeverträge
Zeichensatz der Advanced-Datei; strikte Encoder-Hülle bereitgestellt
Drittanbieter-Runtime-Abhängigkeit
Keine außer Core
Keine außer Core
Univocity
Byte-Form der offiziellen Überschrift
Kanonische unmaskierte Überschrift
Kanonisch im integrierten Writer mit offizieller Überschrift
Textüberschriften werden abweichend maskiert
Plain verwenden, solange kein konkreter Bedarf für individuelle Überschriften benannt werden kann. Speichernde DatevFile für Prüfung/Wiederholung, DatevStreamWriter für einmalige Produktion.
Prüfung in Schichten
## Validierung findet technische Fehler, nicht fachliche Wahrheit
In integrierter Ausgabe immer aktiv
### Struktur- und Kodierungssicherheit
Spaltenbreite/-reihenfolge, bekannte Überschriften, CSV-Syntax/Steuerzeichen, Zeilenlimit und strikte Windows-1252-Darstellbarkeit auf Byte-Ausgabe.
Optionale Plain-Abhängigkeit
### DatevValidator
Callback mit Formatversion und unveränderlicher Zeile. Mit Kontenlänge, Wirtschaftsjahresbeginn und Periode bauen, um kontextbezogene Konto-/Datumsregeln zu prüfen.
Advanced-Konfiguration
### DatevValidationMode
STRICT ergänzt Pflichtfelder und Abhängigkeiten; FIELD_LEVEL prüft gelieferte bekannte Felder; NONE behält strukturelle CSV-/Überschriftsprüfungen.
Immer Sache der Anwendung
### Buchhaltung und Stammdaten
Kontenauswahl, Steuerbehandlung, Gültigkeit im Ziel und mandantenspezifische Anforderungen müssen außerhalb der Bibliothek validiert werden.
Das bloße Einbinden von datev-exporter-field-validator verändert nichts. Der Validator wird an Plain-Builder/-Factory übergeben. Offizielle Advanced-Schemata nutzen standardmäßig STRICT; individuelle Überschriften NONE, weil ihre Fachsemantik unbekannt ist.
Interoperabilität, kein Ersatz
## Der Univocity-Adapter löst genau ein enges Problem
datev-exporter-advanced-univocity nur wählen, wenn die umgebende Anwendung CSV-Ausgabe bereits in Univocity zentralisiert und Überschrift plus Buchungszeilen die beabsichtigte Grenze sind.
```
CsvWriter writer = DatevUnivocityWriters.newCsvWriter(file, outputStream);
DatevUnivocityWriters.writeTo(file, writer);
```
- Ein CsvWriter gibt gleichförmige Sätze aus und kann daher den anders aufgebauten EXTF-Verwaltungssatz mit 31 Feldern nicht erzeugen.
- writeTo lehnt eine Datei mit Metadaten ab. Für eine vollständige Datei den integrierten Advanced-Pfad DatevFile.writeTo(OutputStream) verwenden.
- writeDataTo schreibt ausdrücklich nur Überschrift und Zeilen – selbst wenn Metadaten vorhanden sind.
- Mit unveränderten offiziellen v12/v13-Einstellungen entsprechen Buchungszeilen der integrierten Ausgabe, Textüberschriften werden aber anders maskiert. Keine Aussage über Byte-Gleichheit der Gesamtdatei.
- Das bereitgestellte newCsvWriter meldet nicht darstellbare Zeichen und lässt den Stream offen. Rohe Univocity-Konstruktoren vermeiden, die unzulässige Zeichen durch ? ersetzen können.
Verantwortungsregeln
## Das Ausgabeziel bleibt beim Aufrufer
- Integrierte Writer leeren, aber schließen einen gelieferten OutputStream oder Writer nicht.
- Für kanonische Windows-1252-Bytes den OutputStream-Pfad verwenden. Ein Zeichen-Writer ist nur ein Zeichenvertrag; sein finaler Encoder bleibt Aufgabe des Aufrufers.
- Ungepufferte Datei-/Netzwerkausgabe einmalig puffern. Die Bibliothek wählt bewusst keine dauerhafte Puffergröße.
- Plain und Advanced DatevFile behalten angenommene Zeilen. DatevStreamWriter übergibt jede angenommene Zeile und verwirft ihren Zusammenstellungsspeicher.
- Alle mutablen Exporter-Instanzen sind bewusst single-threaded.
Vor einer volumenbasierten Auswahl das Beispiel für gepuffertes Streaming und den Benchmarkbericht lesen.
Referenz auf Symbolebene
## Versionierte Javadocs für exakte Signaturen
Dieser Leitfaden erklärt Verträge und Entscheidungen. Die generierte API-Seite ist die Quelle für öffentliche Klassen, Methoden und Lebenszyklusdetails:
- Javadoc-Index für Release 0.2.0
- Versionierter Quellcode des ausführbaren Einstiegsbeispiels
- Veröffentlichte BOM auf Maven Central
Das Projekt verwendet Semantic Versioning, öffentliche APIs können sich bis 1.0.0 jedoch zwischen Minor-Versionen ändern. BOM-Version fixieren und beim Upgrade die Release Notes lesen.
---
Source: https://mrtyldr.github.io/datev-exporter/de/fields.html
Feldreferenz · Schema v13 und v12 · 0.2.0
# Alle 125 Buchungsstapel-Spalten in amtlicher Reihenfolge.
Feldnummern, exakte Überschriften, Prüfprogramm-Typen und Längen für Formatversion 13 — mit den Unterschieden, die bei Formatversion 12 zählen.
## Was diese Tabelle ist
Eine Buchungszeile im DATEV-Buchungsstapel hat eine feste Anzahl Spalten in fester Reihenfolge. Formatversion 13 definiert 125 Spalten, Version 12 die ersten 124 und lässt Abw. Skontokonto weg. Die Reihenfolge trägt Bedeutung: eine Zeile ist positionsbasiert, Feld 7 ist Konto — unabhängig davon, ob Feld 6 gefüllt wurde.
Die Tabelle wird aus DatevFieldSpecs erzeugt, der einzigen kanonischen Schemakopie, aus der sich jedes Modul dieser Bibliothek ableitet. Sie ist keine handgepflegte Abschrift und kann daher nicht von dem abweichen, was die Exporter tatsächlich schreiben.
Zu wissen, dass Feld 9 BU-Schlüssel heißt, sagt nichts darüber, welcher Buchungsschlüssel im konkreten Fall richtig ist. Kontenzuordnung, steuerliche Behandlung und Buchungslogik bleiben bei der aufrufenden Anwendung und der steuerlichen Beratung.
## Aufbau des Schemas
Typ
Name im Prüfprogramm
Spalten
Bedeutung
TEXT
Text
84
Gequoteter Textwert; die maximale Länge zählt Zeichen.
NUMBER
Zahl
27
Ungequoteter numerischer Wert mit optionalem Komma als Dezimaltrenner.
DATE
Datum
7
Datum im DATEV-Format.
ACCOUNT
Konto
4
Numerische Kontonummer, zusätzlich durch die Sachkontenlänge eingegrenzt.
AMOUNT
Betrag
3
Positiver Betrag; das Vorzeichen steht im Soll/Haben-Kennzeichen.
## Die fünf Pflichtfelder
Die strikte Validierung meldet einen leeren Wert in diesen Spalten als REQUIRED_FIELD. Jede andere Spalte darf leer bleiben.
#
Amtliche Überschrift
DatevField-Konstante
Typ
1
Umsatz (ohne Soll/Haben-Kz)
AMOUNT
Betrag
2
Soll/Haben-Kennzeichen
DEBIT_CREDIT_FLAG
Text
7
Konto
ACCOUNT
Konto
8
Gegenkonto (ohne BU-Schlüssel)
CONTRA_ACCOUNT
Konto
10
Belegdatum
DOCUMENT_DATE
Datum
## Wiederholende Gruppen und eine Schreibweisen-Falle
Zwei Spaltenfamilien wiederholen sich als Art-/Inhalt-Paare. Wird nur eine Hälfte gefüllt, meldet der strikte Modus DEPENDENT_FIELD_MISSING.
- Beleginfo - Art 1 … Beleginfo - Inhalt 8 — acht Paare, Felder 21–36.
- Zusatzinformation - Art 1 … Zusatzinformation- Inhalt 20 — zwanzig Paare, Felder 48–87.
DATEV schreibt das Paar uneinheitlich: Zusatzinformation - Art 1 mit Leerzeichen um den Bindestrich, Zusatzinformation- Inhalt 1 ohne. Beide Schreibweisen werden exakt reproduziert. Mit den DatevField-Konstanten wird ein Tippfehler zum Compile-Fehler statt zu einer abgelehnten Datei.
## Vollständige Feldtabelle
#
Amtliche Überschrift
DatevField-Konstante
Typ
Max. Länge
Nachkommastellen
Pflicht
In v12
1
Umsatz (ohne Soll/Haben-Kz)
AMOUNT
Betrag
10
2
ja
ja
2
Soll/Haben-Kennzeichen
DEBIT_CREDIT_FLAG
Text
1
—
ja
ja
3
WKZ Umsatz
CURRENCY
Text
3
—
nein
ja
4
Kurs
EXCHANGE_RATE
Zahl
5
6
nein
ja
5
Basis-Umsatz
BASE_AMOUNT
Betrag
10
2
nein
ja
6
WKZ Basis-Umsatz
BASE_CURRENCY
Text
3
—
nein
ja
7
Konto
ACCOUNT
Konto
9
—
ja
ja
8
Gegenkonto (ohne BU-Schlüssel)
CONTRA_ACCOUNT
Konto
9
—
ja
ja
9
BU-Schlüssel
POSTING_KEY
Text
4
—
nein
ja
10
Belegdatum
DOCUMENT_DATE
Datum
8
—
ja
ja
11
Belegfeld 1
DOCUMENT_FIELD_1
Text
36
—
nein
ja
12
Belegfeld 2
DOCUMENT_FIELD_2
Text
12
—
nein
ja
13
Skonto
CASH_DISCOUNT
Betrag
8
2
nein
ja
14
Buchungstext
POSTING_TEXT
Text
60
—
nein
ja
15
Postensperre
ITEM_BLOCK
Zahl
1
—
nein
ja
16
Diverse Adressnummer
MISC_ADDRESS_NUMBER
Text
9
—
nein
ja
17
Geschäftspartnerbank
PARTNER_BANK
Zahl
3
—
nein
ja
18
Sachverhalt
MATTER_CODE
Zahl
2
—
nein
ja
19
Zinssperre
INTEREST_BLOCK
Zahl
1
—
nein
ja
20
Beleglink
DOCUMENT_LINK
Text
210
—
nein
ja
21
Beleginfo - Art 1
DOCUMENT_INFO_TYPE_1
Text
20
—
nein
ja
22
Beleginfo - Inhalt 1
DOCUMENT_INFO_CONTENT_1
Text
210
—
nein
ja
23
Beleginfo - Art 2
DOCUMENT_INFO_TYPE_2
Text
20
—
nein
ja
24
Beleginfo - Inhalt 2
DOCUMENT_INFO_CONTENT_2
Text
210
—
nein
ja
25
Beleginfo - Art 3
DOCUMENT_INFO_TYPE_3
Text
20
—
nein
ja
26
Beleginfo - Inhalt 3
DOCUMENT_INFO_CONTENT_3
Text
210
—
nein
ja
27
Beleginfo - Art 4
DOCUMENT_INFO_TYPE_4
Text
20
—
nein
ja
28
Beleginfo - Inhalt 4
DOCUMENT_INFO_CONTENT_4
Text
210
—
nein
ja
29
Beleginfo - Art 5
DOCUMENT_INFO_TYPE_5
Text
20
—
nein
ja
30
Beleginfo - Inhalt 5
DOCUMENT_INFO_CONTENT_5
Text
210
—
nein
ja
31
Beleginfo - Art 6
DOCUMENT_INFO_TYPE_6
Text
20
—
nein
ja
32
Beleginfo - Inhalt 6
DOCUMENT_INFO_CONTENT_6
Text
210
—
nein
ja
33
Beleginfo - Art 7
DOCUMENT_INFO_TYPE_7
Text
20
—
nein
ja
34
Beleginfo - Inhalt 7
DOCUMENT_INFO_CONTENT_7
Text
210
—
nein
ja
35
Beleginfo - Art 8
DOCUMENT_INFO_TYPE_8
Text
20
—
nein
ja
36
Beleginfo - Inhalt 8
DOCUMENT_INFO_CONTENT_8
Text
210
—
nein
ja
37
KOST1 - Kostenstelle
COST_CENTER_1
Text
36
—
nein
ja
38
KOST2 - Kostenstelle
COST_CENTER_2
Text
36
—
nein
ja
39
Kost-Menge
COST_QUANTITY
Zahl
12
4
nein
ja
40
EU-Land u. UStID (Bestimmung)
EU_COUNTRY_VAT_ID_DESTINATION
Text
15
—
nein
ja
41
EU-Steuersatz (Bestimmung)
EU_TAX_RATE_DESTINATION
Zahl
2
2
nein
ja
42
Abw. Versteuerungsart
DIFFERING_TAXATION_TYPE
Text
1
—
nein
ja
43
Sachverhalt L+L
MATTER_CODE_LL
Zahl
3
—
nein
ja
44
Funktionsergänzung L+L
FUNCTION_SUPPLEMENT_LL
Zahl
3
—
nein
ja
45
BU 49 Hauptfunktionstyp
BU49_MAIN_FUNCTION_TYPE
Zahl
1
—
nein
ja
46
BU 49 Hauptfunktionsnummer
BU49_MAIN_FUNCTION_NUMBER
Zahl
2
—
nein
ja
47
BU 49 Funktionsergänzung
BU49_FUNCTION_SUPPLEMENT
Zahl
3
—
nein
ja
48
Zusatzinformation - Art 1
ADDITIONAL_INFO_TYPE_1
Text
20
—
nein
ja
49
Zusatzinformation- Inhalt 1
ADDITIONAL_INFO_CONTENT_1
Text
210
—
nein
ja
50
Zusatzinformation - Art 2
ADDITIONAL_INFO_TYPE_2
Text
20
—
nein
ja
51
Zusatzinformation- Inhalt 2
ADDITIONAL_INFO_CONTENT_2
Text
210
—
nein
ja
52
Zusatzinformation - Art 3
ADDITIONAL_INFO_TYPE_3
Text
20
—
nein
ja
53
Zusatzinformation- Inhalt 3
ADDITIONAL_INFO_CONTENT_3
Text
210
—
nein
ja
54
Zusatzinformation - Art 4
ADDITIONAL_INFO_TYPE_4
Text
20
—
nein
ja
55
Zusatzinformation- Inhalt 4
ADDITIONAL_INFO_CONTENT_4
Text
210
—
nein
ja
56
Zusatzinformation - Art 5
ADDITIONAL_INFO_TYPE_5
Text
20
—
nein
ja
57
Zusatzinformation- Inhalt 5
ADDITIONAL_INFO_CONTENT_5
Text
210
—
nein
ja
58
Zusatzinformation - Art 6
ADDITIONAL_INFO_TYPE_6
Text
20
—
nein
ja
59
Zusatzinformation- Inhalt 6
ADDITIONAL_INFO_CONTENT_6
Text
210
—
nein
ja
60
Zusatzinformation - Art 7
ADDITIONAL_INFO_TYPE_7
Text
20
—
nein
ja
61
Zusatzinformation- Inhalt 7
ADDITIONAL_INFO_CONTENT_7
Text
210
—
nein
ja
62
Zusatzinformation - Art 8
ADDITIONAL_INFO_TYPE_8
Text
20
—
nein
ja
63
Zusatzinformation- Inhalt 8
ADDITIONAL_INFO_CONTENT_8
Text
210
—
nein
ja
64
Zusatzinformation - Art 9
ADDITIONAL_INFO_TYPE_9
Text
20
—
nein
ja
65
Zusatzinformation- Inhalt 9
ADDITIONAL_INFO_CONTENT_9
Text
210
—
nein
ja
66
Zusatzinformation - Art 10
ADDITIONAL_INFO_TYPE_10
Text
20
—
nein
ja
67
Zusatzinformation- Inhalt 10
ADDITIONAL_INFO_CONTENT_10
Text
210
—
nein
ja
68
Zusatzinformation - Art 11
ADDITIONAL_INFO_TYPE_11
Text
20
—
nein
ja
69
Zusatzinformation- Inhalt 11
ADDITIONAL_INFO_CONTENT_11
Text
210
—
nein
ja
70
Zusatzinformation - Art 12
ADDITIONAL_INFO_TYPE_12
Text
20
—
nein
ja
71
Zusatzinformation- Inhalt 12
ADDITIONAL_INFO_CONTENT_12
Text
210
—
nein
ja
72
Zusatzinformation - Art 13
ADDITIONAL_INFO_TYPE_13
Text
20
—
nein
ja
73
Zusatzinformation- Inhalt 13
ADDITIONAL_INFO_CONTENT_13
Text
210
—
nein
ja
74
Zusatzinformation - Art 14
ADDITIONAL_INFO_TYPE_14
Text
20
—
nein
ja
75
Zusatzinformation- Inhalt 14
ADDITIONAL_INFO_CONTENT_14
Text
210
—
nein
ja
76
Zusatzinformation - Art 15
ADDITIONAL_INFO_TYPE_15
Text
20
—
nein
ja
77
Zusatzinformation- Inhalt 15
ADDITIONAL_INFO_CONTENT_15
Text
210
—
nein
ja
78
Zusatzinformation - Art 16
ADDITIONAL_INFO_TYPE_16
Text
20
—
nein
ja
79
Zusatzinformation- Inhalt 16
ADDITIONAL_INFO_CONTENT_16
Text
210
—
nein
ja
80
Zusatzinformation - Art 17
ADDITIONAL_INFO_TYPE_17
Text
20
—
nein
ja
81
Zusatzinformation- Inhalt 17
ADDITIONAL_INFO_CONTENT_17
Text
210
—
nein
ja
82
Zusatzinformation - Art 18
ADDITIONAL_INFO_TYPE_18
Text
20
—
nein
ja
83
Zusatzinformation- Inhalt 18
ADDITIONAL_INFO_CONTENT_18
Text
210
—
nein
ja
84
Zusatzinformation - Art 19
ADDITIONAL_INFO_TYPE_19
Text
20
—
nein
ja
85
Zusatzinformation- Inhalt 19
ADDITIONAL_INFO_CONTENT_19
Text
210
—
nein
ja
86
Zusatzinformation - Art 20
ADDITIONAL_INFO_TYPE_20
Text
20
—
nein
ja
87
Zusatzinformation- Inhalt 20
ADDITIONAL_INFO_CONTENT_20
Text
210
—
nein
ja
88
Stück
PIECES
Zahl
8
—
nein
ja
89
Gewicht
WEIGHT
Zahl
8
2
nein
ja
90
Zahlweise
PAYMENT_METHOD
Zahl
2
—
nein
ja
91
Forderungsart
RECEIVABLE_TYPE
Text
10
—
nein
ja
92
Veranlagungsjahr
ASSESSMENT_YEAR
Zahl
4
—
nein
ja
93
Zugeordnete Fälligkeit
ASSIGNED_DUE_DATE
Datum
8
—
nein
ja
94
Skontotyp
CASH_DISCOUNT_TYPE
Zahl
1
—
nein
ja
95
Auftragsnummer
ORDER_NUMBER
Text
30
—
nein
ja
96
Buchungstyp
POSTING_TYPE
Text
2
—
nein
ja
97
USt-Schlüssel (Anzahlungen)
VAT_KEY_PREPAYMENT
Zahl
2
—
nein
ja
98
EU-Land (Anzahlungen)
EU_COUNTRY_PREPAYMENT
Text
2
—
nein
ja
99
Sachverhalt L+L (Anzahlungen)
MATTER_CODE_LL_PREPAYMENT
Zahl
3
—
nein
ja
100
EU-Steuersatz (Anzahlungen)
EU_TAX_RATE_PREPAYMENT
Zahl
2
2
nein
ja
101
Erlöskonto (Anzahlungen)
REVENUE_ACCOUNT_PREPAYMENT
Konto
9
—
nein
ja
102
Herkunft-Kz
ORIGIN_CODE
Text
2
—
nein
ja
103
Buchungs GUID
POSTING_GUID
Text
36
—
nein
ja
104
KOST-Datum
COST_DATE
Datum
8
—
nein
ja
105
SEPA-Mandatsreferenz
SEPA_MANDATE_REFERENCE
Text
35
—
nein
ja
106
Skontosperre
CASH_DISCOUNT_BLOCK
Zahl
1
—
nein
ja
107
Gesellschaftername
SHAREHOLDER_NAME
Text
76
—
nein
ja
108
Beteiligtennummer
PARTICIPANT_NUMBER
Zahl
4
—
nein
ja
109
Identifikationsnummer
IDENTIFICATION_NUMBER
Text
11
—
nein
ja
110
Zeichnernummer
SUBSCRIBER_NUMBER
Text
20
—
nein
ja
111
Postensperre bis
ITEM_BLOCK_UNTIL
Datum
8
—
nein
ja
112
Bezeichnung SoBil-Sachverhalt
SOBIL_MATTER_LABEL
Text
30
—
nein
ja
113
Kennzeichen SoBil-Buchung
SOBIL_POSTING_FLAG
Zahl
2
—
nein
ja
114
Festschreibung
FINAL_POSTING_FLAG
Zahl
1
—
nein
ja
115
Leistungsdatum
SERVICE_DATE
Datum
8
—
nein
ja
116
Datum Zuord. Steuerperiode
TAX_PERIOD_DATE
Datum
8
—
nein
ja
117
Fälligkeit
DUE_DATE
Datum
8
—
nein
ja
118
Generalumkehr (GU)
GENERAL_REVERSAL
Text
1
—
nein
ja
119
Steuersatz
TAX_RATE
Zahl
2
2
nein
ja
120
Land
COUNTRY
Text
2
—
nein
ja
121
Abrechnungsreferenz
SETTLEMENT_REFERENCE
Text
50
—
nein
ja
122
BVV-Position
BVV_POSITION
Zahl
1
—
nein
ja
123
EU-Land u. UStID (Ursprung)
EU_COUNTRY_VAT_ID_ORIGIN
Text
15
—
nein
ja
124
EU-Steuersatz (Ursprung)
EU_TAX_RATE_ORIGIN
Zahl
2
2
nein
ja
125
Abw. Skontokonto
DIFFERING_CASH_DISCOUNT_ACCOUNT
Konto
8
—
nein
nein
## Ein Feld aus Java ansprechen
Jede DatevColumn-Factory akzeptiert entweder die Enum-Konstante oder die Überschrift als Zeichenkette; beide erzeugen identische Ausgabe. Die Konstante wird zur Übersetzungszeit geprüft.
```
import io.github.mrtyldr.datev.core.DatevColumn;
import io.github.mrtyldr.datev.core.DatevField;
import io.github.mrtyldr.datev.core.DatevSchema;
// Field 7, "Konto" — compile-checked.
DatevColumn account = DatevColumn.account(DatevField.ACCOUNT, 1000);
// Identical output, but a typo would only surface at runtime.
DatevColumn same = DatevColumn.account("Konto", 1000);
int number = DatevField.ACCOUNT.fieldNumber(); // 7
String heading = DatevField.ACCOUNT.heading(); // "Konto"
boolean inLegacy = DatevField.DIFFERING_CASH_DISCOUNT_ACCOUNT
.isPresentIn(DatevSchema.LEGACY_V12); // false
```
Die DatevField-Konstanten sind in Ausgabereihenfolge deklariert, daher ist ordinal() + 1 die DATEV-Feldnummer. isPresentIn(DatevSchema.LEGACY_V12) beantwortet die Version-12-Frage für jedes Feld.
## Verwandte Referenzen
- Validierungsfehler — die sechs Fehlercodes erklärt
- EXTF-Header — der Verwaltungssatz mit 31 Feldern
- Kodierung — Windows-1252, CRLF, Quoting und Umlaute
---
Source: https://mrtyldr.github.io/datev-exporter/de/validation-errors.html
Validierungsreferenz · 0.2.0
# Sechs Fehlercodes und was sie jeweils aussagen.
Jeder Validierungsfehler trägt einen stabilen maschinenlesbaren Code, die DATEV-Feldnummer und die amtliche Spaltenbezeichnung. Hier steht, was den Code auslöst und was zu ändern ist.
## Drei Prüftiefen
Die Tiefe ist eine bewusste Entscheidung je Datei. Ein strikterer Modus ändert nie die geschriebenen Bytes, sondern nur, was vorher abgelehnt wird.
Modus
Was geprüft wird
Mögliche Codes
NONE
Keine semantische Prüfung. Die strukturellen Prüfungen des Exporters — Zeilenbreite, Steuerzeichen, Kodierbarkeit — gelten weiterhin.
—
FIELD_LEVEL
Jede gefüllte Zelle gegen ihre amtliche Felddefinition.
INVALID_FORMAT, VALUE_OUT_OF_RANGE, TEXT_TOO_LONG, UNMAPPABLE_CHARACTER
STRICT
Alles davon, zusätzlich Pflichtfelder und Feldabhängigkeiten.
alle sechs
## Die sechs Codes
Code
Wird ausgelöst, wenn
Übliche Behebung
REQUIRED_FIELD
Ein vom amtlichen Prüfprogramm als notwendig markiertes Feld ist leer — im strikten Modus auf einem amtlichen Schema.
Feld füllen. Betroffen sind nur fünf Spalten: Umsatz, Soll/Haben-Kennzeichen, Konto, Gegenkonto und Belegdatum.
INVALID_FORMAT
Ein Wert entspricht nicht der von DATEV geforderten Darstellung — eine fehlerhafte Zahl, ein Datum ohne realen Kalenderbezug, ein Kennzeichen außerhalb der erlaubten Menge oder ein Steuer- bzw. Zeilentrennzeichen innerhalb einer Zelle.
Den Wert so formatieren, wie DATEV ihn erwartet, nicht wie das eigene Locale ihn ausgibt. Zeilenumbrüche und Tabulatoren aus Freitext entfernen.
VALUE_OUT_OF_RANGE
Der Wert ist syntaktisch gültig, überschreitet aber seinen Bereich — zu viele Vorkommastellen, zu viele Nachkommastellen oder eine Kontonummer breiter als die konfigurierte Sachkontenlänge.
Maximale Länge und Nachkommastellen in der Feldreferenz prüfen und sicherstellen, dass die Sachkontenlänge in den Metadaten zum Mandanten passt.
TEXT_TOO_LONG
Ein Textwert überschreitet die maximale Zeichenzahl des Feldes.
Bewusst in der eigenen Zuordnung kürzen. Es wird nicht still gekürzt, weil der Verlust eines Teils des Buchungstexts eine fachliche Entscheidung ist.
UNMAPPABLE_CHARACTER
Der Wert enthält ein Zeichen, das Windows-1252 nicht darstellen kann.
Das Zeichen vor dem Export transliterieren oder ersetzen. Die Kodierungsreferenz zeigt, welche Zeichen erhalten bleiben.
DEPENDENT_FIELD_MISSING
Im strikten Modus wurde eine Hälfte eines Feldpaares ohne die andere gefüllt.
Beide Hälften füllen — oder keine.
## Die Feldpaare
Der strikte Modus erzwingt diese Paare. Wird nur eine Seite gefüllt, entsteht DEPENDENT_FIELD_MISSING auf der fehlenden Seite.
- Basis-Umsatz ↔ WKZ Basis-Umsatz (Felder 5 und 6).
- Beleginfo - Art n ↔ Beleginfo - Inhalt n für n = 1…8.
- Zusatzinformation - Art n ↔ Zusatzinformation- Inhalt n für n = 1…20.
## Kontext schärft die Prüfungen
Manche Regeln lassen sich nicht allein aus dem Schema entscheiden. Ein Validierungskontext trägt die Angaben, die sie entscheidbar machen; ohne ihn werden genau diese Prüfungen übersprungen statt geraten.
- Die Sachkontenlänge begrenzt die Breite von Konto und Gegenkonto.
- Wirtschaftsjahresbeginn und Buchungszeitraum erlauben es, das vierstellige Belegdatum gegen reale Kalenderdaten aufzulösen.
Diese Prüfungen bestätigen, dass die Datei dem technischen Schema entspricht. Sie sagen nichts darüber aus, ob die Buchungen fachlich richtig sind oder ob ein bestimmtes DATEV-Produkt in einer bestimmten Konfiguration die Datei annimmt.
## Fehler im Code auswerten
Eine abgelehnte Zeile löst eine DatevValidationException aus, die die vollständige Fehlerliste trägt. Jeder Fehler behält Code, Feldnummer und amtliche Spaltenbezeichnung, sodass sich Fehler protokollieren oder abbilden lassen, ohne Meldungstexte zu parsen.
```
import io.github.mrtyldr.datev.core.DatevValidationError;
import io.github.mrtyldr.datev.core.DatevValidationException;
try {
file.append(columns);
} catch (DatevValidationException failure) {
for (DatevValidationError error : failure.errors()) {
log.warn("field {} ({}): {} — {}",
error.fieldNumber(),
error.canonicalKey(),
error.code(),
error.message());
}
}
```
## Verwandte Referenzen
- Feldreferenz — alle 125 Buchungsstapel-Spalten
- EXTF-Header — der Verwaltungssatz mit 31 Feldern
- Kodierung — Windows-1252, CRLF, Quoting und Umlaute
---
Source: https://mrtyldr.github.io/datev-exporter/de/extf-header.html
Formatreferenz · EXTF · 0.2.0
# Die Zeile vor den Überschriften.
Eine Buchungsstapel-Datei beginnt mit einem Verwaltungssatz, dessen Aufbau nichts mit den darunter liegenden Buchungszeilen zu tun hat. Fehler hier sind der häufigste Grund, warum ein sonst korrekter Export abgelehnt wird.
## Drei Sätze, zwei Formen
Eine vollständige Datei besteht aus drei Schichten: dem EXTF-Verwaltungssatz, der exakten versionierten Spaltenüberschrift und den Buchungszeilen. Nur die letzten beiden teilen ihre Form. Der Verwaltungssatz hat immer 31 Felder, unabhängig von der Formatversion.
Die ersten fünf Felder sind feste Kennungen. An ihnen erkennt ein Leser die Datei überhaupt erst:
Feld
Wert
Bedeutung
1
EXTF
Kennzeichnet eine EXTF-Exportdatei.
2
700
Header-Version.
3
21
Formatkategorie für Buchungsstapel.
4
Buchungsstapel
Formatname.
5
13 / 12
Datenformatversion: 13 oder 12.
## Ein echter Verwaltungssatz
Diese Zeilen erzeugt die Bibliothek selbst, aus Metadaten mit festem Zeitstempel, damit die Ausgabe reproduzierbar ist.
Formatversion 13
```
"EXTF";700;21;"Buchungsstapel";13;20260812093000000;;"RE";"my_application";"";1001;1;20260101;4;20260801;20260831;"August 2026";"";1;0;1;"EUR";;"";;;"";;;"";"my-application"
```
Formatversion 12 — identisch bis auf Feld 5
```
"EXTF";700;21;"Buchungsstapel";12;20260812093000000;;"RE";"my_application";"";1001;1;20260101;4;20260801;20260831;"August 2026";"";1;0;1;"EUR";;"";;;"";;;"";"my-application"
```
Reservierte Felder werden als leere Zellen geschrieben, und Textfelder bleiben auch leer gequotet. Ein Feld wegzulassen statt es zu leeren verschiebt jedes folgende Feld um eine Position.
## Formate, über die man stolpert
- Der Erstellungszeitstempel nutzt yyyyMMddHHmmssSSS — 17 Ziffern inklusive Millisekunden, ungequotet.
- Wirtschaftsjahresbeginn und Buchungszeitraum nutzen yyyyMMdd, ungequotet.
- Textfelder werden gequotet, auch die vorgesehenen leeren. Ein Anführungszeichen in der Anwendungsinformation wird durch Verdopplung maskiert.
- Numerische Felder bleiben ungequotet, einschließlich Berater- und Mandantennummer.
## Die kodierten Felder
Vier Felder nehmen Werte aus einer geschlossenen Menge statt freier Eingabe.
Konstante
DATEV-Wert
FINANCIAL_ACCOUNTING
1
ANNUAL_FINANCIAL_STATEMENTS
2
Konstante
DATEV-Wert
INDEPENDENT
0
TAX_LAW
30
CALCULATION
40
COMMERCIAL_LAW
50
IFRS
64
## Aufbau aus Java
Die Metadaten werden einmal je Datei gebaut und bei der Konstruktion validiert, sodass eine unmögliche Kombination scheitert, bevor eine Zeile geschrieben wird. Der Builder wählt die Formatversion, und der Exporter lehnt einen Verwaltungssatz ab, dessen Version nicht zur Überschrift passt.
```
import io.github.mrtyldr.datev.core.DatevMetadata;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Currency;
DatevMetadata metadata = DatevMetadata.bookingBatchV13()
.createdAt(LocalDateTime.now())
.origin("RE")
.exportedBy("my_application")
.advisorNumber(1001)
.clientNumber(1)
.fiscalYearStart(LocalDate.of(2026, 1, 1))
.accountLength(4)
.period(LocalDate.of(2026, 8, 1), LocalDate.of(2026, 8, 31))
.description("August 2026")
.currency(Currency.getInstance("EUR"))
.applicationInformation("my-application")
.build();
String record = metadata.toCsvLine(); // the 31-field management record
```
Ein v12-Verwaltungssatz lässt sich nicht mit der 125-spaltigen v13-Überschrift kombinieren. Der Builder weist die Abweichung zurück, statt eine Datei zu schreiben, die kein Importeur deuten kann.
## Verwandte Referenzen
- Feldreferenz — alle 125 Buchungsstapel-Spalten
- Validierungsfehler — die sechs Fehlercodes erklärt
- Kodierung — Windows-1252, CRLF, Quoting und Umlaute
---
Source: https://mrtyldr.github.io/datev-exporter/de/encoding.html
Codec-Referenz · 0.2.0
# Windows-1252 ist kein Detail, das warten kann.
Eine Buchungsstapel-Datei besteht aus Bytes, nicht aus Text. Umlaute überstehen das; ein türkisches punktloses i nicht. Ein unbedachter UTF-8-Schritt nach dem Export macht alles zunichte.
## Der Byte-Vertrag
Eigenschaft
Wert
Zeichenkodierung
windows-1252
Satztrenner
\r\n (CRLF)
Feldtrenner
;
Anführungszeichen
"
Maskiertes Anführungszeichen
""
## Wann ein Wert gequotet wird
Zwei unabhängige Regeln entscheiden über das Quoting, beide werden angewendet.
- Amtliche Textspalten werden immer gequotet, auch wenn sie leer sind. 84 der 125 Spalten in Version 13 sind Textspalten.
- Jeder andere Wert wird nur gequotet, wenn es nötig ist — also wenn er ein Semikolon oder ein Anführungszeichen enthält.
- Ein enthaltenes Anführungszeichen wird verdoppelt, nie mit Backslash maskiert.
## Welche Zeichen überstehen
Windows-1252 ist eine Ein-Byte-Kodierung und kann höchstens 256 Zeichen darstellen. Deutscher Text liegt bequem darin, viel anderer Text nicht.
Kodierbar — werden unverändert geschrieben
```
ä ö ü ß Ä Ö Ü € § µ ° á é í ó ú ñ ç å ø æ š ž
```
Nicht kodierbar — abgelehnt als UNMAPPABLE_CHARACTER
```
ı ğ ş ł ą č ř ő ū 日 😀
```
Ein Wert mit einem nicht kodierbaren Zeichen wird abgelehnt statt still durch ein Fragezeichen ersetzt, weil ein beschädigter Buchungstext später schwerer auffällt als ein jetzt fehlgeschlagener Export. Wenn die Quelldaten solche Zeichen enthalten können, sollte in der eigenen Zuordnung bewusst transliteriert werden.
## Steuerzeichen
Steuer-, Zeilen- und Absatztrennzeichen werden an jeder Stelle einer Zelle abgelehnt und als INVALID_FORMAT gemeldet. Ein Zeilenumbruch in einem Buchungstext würde sonst eine Buchungszeile in zwei unbrauchbare Sätze zerlegen.
## Wie Exporte nach dem Schreiben beschädigt werden
Die Bibliothek kontrolliert die Bytes, die sie schreibt. Alles danach liegt in eigener Verantwortung.
- Ein Texteditor, der die Datei öffnet und als UTF-8 zurückspeichert — jeder Umlaut wird zu zwei Bytes und die Datei ist ungültig.
- Ein Übertragungs- oder Archivierungsschritt im Textmodus, der CRLF zu LF umschreibt.
- Das Zurücklesen der Datei mit dem Plattform-Standardzeichensatz statt Windows-1252.
- Eine Template- oder Logging-Schicht, die die Ausgabe auf Unicode NFD normalisiert und Umlaute in Grundbuchstabe plus kombinierendes Zeichen zerlegt.
Eine Datei, die im Editor richtig aussieht, kann bereits defekt sein. Bytelänge und Kodierung prüfen und die erzeugte Datei zwischen Export und Import unangetastet lassen.
## Verwandte Referenzen
- Feldreferenz — alle 125 Buchungsstapel-Spalten
- Validierungsfehler — die sechs Fehlercodes erklärt
- EXTF-Header — der Verwaltungssatz mit 31 Feldern
---
Source: https://mrtyldr.github.io/datev-exporter/de/benchmarks.html
Lokal gemessen · v0.2.0 · Java 17
# Eine vollständige EXTF-Datei mit 99.999 Zeilen.
Ein reproduzierbarer JMH-Lauf vergleicht drei streng validierte Exportpfade, erfasst die kumulative Allokation und bewahrt die Messunsicherheit, statt aus einem Laptop-Lauf eine allgemeingültige Aussage zu machen.
Beobachtete Daten
## Dieser Lauf löste keinen Zeitunterschied zwischen den beiden Plain-Pfaden auf.
Eine Operation erzeugt eine vollständige EXTF-v13-Datei aus Verwaltungssatz, 125-spaltiger Überschrift und 99.999 Buchungszeilen. In den Zeit- und Allokationsspalten ist weniger besser. Die ±-Werte sind die Halbbreiten der JMH-99,9-%-Konfidenzintervalle über zehn Messstichproben unter der Normalverteilungsannahme von JMH.
Exportpfad
Zeit / Datei
Abgeleitete Zeit / Zeile
Abgeleitete Zeilen / Sekunde
Allokierte Bytes / Datei
Abgeleitete allokierte Bytes / Zeile
Plain Forward-onlyDatevStreamWriter
670,193 ± 34,910 ms
6,702 µs
149.209
980.975.803 ± 10.710.036 B
9.809,86 B
Plain RetainedDatevFile
670,000 ± 15,068 ms
6,700 µs
149.252
1.011.067.254 ± 10.710.046 B
10.110,77 B
Advanced Retainedadvanced.DatevFile
742,976 ± 51,878 ms
7,430 µs
134.593
966.056.224 ± 10.710.041 B
9.660,66 B
Die Mittelwerte der beiden Plain-Pfade unterscheiden sich nur um 0,03 % und damit weit weniger als ihre ausgewiesene Unsicherheit; dieser Lauf trägt daher keine zeitliche Rangfolge. Forward-only allokierte in dieser Arbeitslast rund 3,0 % weniger kumulative Bytes als Plain Retained. Advanced Retained zeigte den niedrigsten Allokationswert und den höchsten beobachteten Zeitmittelwert; dieser einzelne Lauf begründet jedoch keine allgemeingültige Rangfolge.
Produktentscheidung
## Zuerst den Lebenszyklus wählen, nicht die kleinste Benchmark-Zahl.
### Forward-only für einmalige Exporte mit hohem Volumen
DatevStreamWriter validiert, serialisiert und übergibt jede vollständige Zeile, ohne sie in einer bibliothekseigenen Sammlung zu speichern. Der lebende, zurückgehaltene Zeilenzustand ist damit proportional zu einer Zeile statt zur Gesamtzahl. Diese Entwurfseigenschaft – keine Geschwindigkeitsbehauptung – ist der stärkste Grund für Forward-only bei einem einmaligen Export mit 99.999 Zeilen.
### Retained verwenden, wenn Zeilen verfügbar bleiben müssen
Die speichernden APIs erlauben Prüfung, Iteration und verzögerte Ausgabe. Dieser Lebenszyklus ist sinnvoll, wenn der Aufrufer Zeilen erneut prüfen oder ausgeben muss; dieser Lauf löste gegenüber Forward-only keinen Zeitunterschied auf. Die ausgerichteten Zeilen bleiben zwangsläufig bis zur Freigabe des Dateiobjekts im Speicher.
### Allokation ist nicht gleich belegter Heap
JMH gc.alloc.rate.norm erfasst alle während einer Operation allokierten Bytes, einschließlich kurzlebiger Validierungs- und Serialisierungsobjekte. Es misst nicht den maximal lebenden Heap. Das Advanced-Retained-Ergebnis zeigt den Unterschied: Es allokierte hier kumulativ am wenigsten, obwohl es ausgerichtete Zeilen speichert. Zur Quantifizierung des Spitzenverbrauchs wäre eine separate Live-Set- oder Heap-Occupancy-Untersuchung erforderlich.
Gemessene Arbeitslast
## Eine dünn belegte, aber nicht triviale feste Zeile.
- Format: vollständiger DATEV-Buchungsstapel / EXTF v13, Windows-1252 und CRLF.
- Größe: 125 Spalten; 99.999 Buchungszeilen als unterstütztes Dateimaximum.
- Belegung: sechs nicht leere Felder je Zeile: Betrag, Soll/Haben-Kennzeichen, Konto, Gegenkonto, Belegdatum und Buchungstext.
- Maskierung: Der Buchungstext lautet Müller; Beleg "42" € und beansprucht Windows-1252-, Trennzeichen- und Anführungszeichenbehandlung.
- Validierung: metadatenbezogene strenge semantische Validierung bei jedem Append. Plain verwendet DatevValidator, Advanced den eingebauten Modus STRICT.
- Ausgabe: Alle Pfade werden bytegenau verglichen und erzeugen exakt 33.602.459 Bytes: 2.795 feste Verwaltungs-/Überschriftsbytes plus 336 Bytes je Buchungszeile.
Für jede Zeile wird dieselbe unveränderliche Map mit sechs Einträgen übergeben. Zeilenausrichtung, Validierung und Serialisierung liegen im Messintervall; die vorgelagerte Datensatzerzeugung und fachliche Kontierungslogik nicht.
Messvertrag
## Umgebung und JMH-Konfiguration.
Gemessene Bibliothek
v0.2.0 · Commit 06fa7ae
Messdatum
12. August 2026
Rechner
Apple M1 Pro, 10 logische CPUs, 32 GiB RAM, aarch64
Betriebssystem
macOS 26.5.2 (Build 25F84)
JVM
Eclipse Temurin 17.0.19+10; -Xms1g -Xmx1g -XX:+AlwaysPreTouch
Messgerüst
JMH 1.37, Average-Time-Modus, ein Thread, zwei Forks
Iterationen
Je Fork: drei × 1 s Warmup, danach fünf × 1 s Messung
Profiler
JMH gc; normalisierte Allokation in Bytes je Operation
Ziel
Ein vorab dimensionierter, wiederverwendeter ByteArrayOutputStream, außerhalb jeder Messoperation zurückgesetzt
I/O
Byte-Serialisierung und Schreiben ins Ziel enthalten; Dateisystem, Netzwerk und Zielallokation ausgeschlossen
Jeder gemessene Aufruf erstellt seinen Exporter und führt alle 99.999 Appends sowie die abschließende Ausgabe aus. Unveränderliche Testdaten, Zielkapazität und der erste Bytegleichheitsvergleich werden vor der Messung vorbereitet. Die letzte Ausgabe wird nach dem Lauf erneut geprüft.
Selbst ausführen
## Die Maximalzeilen-Task fixiert die wichtigen Eingaben.
```
git clone https://github.com/mrtyldr/datev-exporter.git
cd datev-exporter
git checkout cb91f5dd8b174bb4e10d98a8a7cc93f007483042
./gradlew --no-daemon :datev-exporter-benchmarks:jmhMaxRows
```
Die Task wählt die Adoptium-Java-17-Toolchain und verwendet diese JMH-Einstellungen:
```
-p rowCount=99999
-wi 3 -w 1s
-i 5 -r 1s
-f 2 -t 1
-jvmArgs "-Xms1g -Xmx1g -XX:+AlwaysPreTouch"
-prof gc -rf json
```
Das erzeugte JSON liegt unter datev-exporter-benchmarks/build/results/jmh/max-rows-gc.json. Die veröffentlichte Zusammenfassung bewahrt jede rohe Zeit- und Allokationsstichprobe:
- Maschinenlesbares Ergebnis und Rohwerte
- Benchmark-Quellcode
- Versionierte Java-API
Nicht verallgemeinern
## Was dieser Lauf nicht belegt.
- Es ist ein Lauf auf einem Entwickler-Laptop ohne dedizierte Host-Isolation, CPU-Pinning oder thermische Kontrolle.
- Die zehn Stichproben schätzen den eingeschwungenen Zustand dieser Arbeitslast; sie sind keine Produktions-Latenzperzentile.
- Zeilen pro Sekunde ist aus der durchschnittlichen Dateizeit berechnet und kein mehrthreadiger Durchsatztest.
- Die dünn belegte feste Zeile bildet nicht jede Felddichte, Wertlänge, Validierungsverletzung oder vorgelagerte Objektallokation ab.
- Das In-Memory-Ziel schließt Dateisystem, Netzwerk, Verschlüsselung, Kompression und aufruferseitige Pufferung aus.
- Der Profiler misst kumulative Allokation, nicht maximalen RSS, maximal lebenden Heap oder Retained Size.
- Ein Univocity-Pfad ist nicht enthalten: Der Adapter hat eine andere Ausgabegrenze und kann die hier gemessene vollständige Datei aus Verwaltungssatz und Buchungen nicht erzeugen.
Diese Zahlen dienen zum Verständnis der Implementierung und als reproduzierbare Vergleichsbasis auf der eigenen Zielhardware – nicht als SLA. Die Kompatibilitätsnachweise und Grenzen sind separat zu bewerten; Geschwindigkeit belegt keine DATEV-Importannahme.