# How to Parse YAML from Files or Input Streams with yaml-cpp

> Easily parse YAML from files or input streams using yaml-cpp. Learn how to use YAML::Load, YAML::LoadFile, and YAML::LoadAll for efficient YAML parsing and manipulation.

- Repository: [Jesse Beder/yaml-cpp](https://github.com/jbeder/yaml-cpp)
- Tags: how-to-guide
- Published: 2026-07-11

---

**You can parse YAML in yaml‑cpp using the header‑only convenience functions `YAML::Load`, `YAML::LoadFile`, and `YAML::LoadAll`, which internally instantiate a `Parser` and `NodeBuilder` to transform any `std::istream` or file into a tree of `YAML::Node` objects.**

The `yaml‑cpp` library (available at `jbeder/yaml‑cpp`) provides a high‑level C++ API for consuming YAML documents. Whether you are reading from strings, files, or arbitrary input streams, the library exposes a concise interface that hides a sophisticated pipeline of lexical scanning, directive processing, and node construction. Understanding this architecture helps you choose the right entry point for your specific use case.

## The Internal Parsing Pipeline

When you call any of the public `Load*` functions, the library creates a **Parser** object that orchestrates the conversion from raw text to structured data. The flow through [`src/parser.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/parser.cpp) follows four distinct phases:

1. **Stream initialization** – The `Parser::Parser(std::istream&)` constructor (defined in [`src/parser.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/parser.cpp) at line 22) initializes a `Scanner` over the supplied stream and prepares a fresh `Directives` container to track `%YAML` and `%TAG` directives.
2. **Directive processing** – `Parser::ParseDirectives` (line 56) consumes any leading directives and stores them in the `Directives` object.
3. **Document parsing** – `Parser::HandleNextDocument` (line 27) instantiates a `SingleDocParser` that walks the token stream, generates parsing events, and feeds them to an `EventHandler`.
4. **Node construction** – A `NodeBuilder` receives the events and assembles the final `Node` tree, returning the root node to the caller.

This design deliberately separates **lexical scanning** (`Scanner`), **directive handling** (`Directives`), **document parsing** (`SingleDocParser`), and **node construction** (`NodeBuilder`), making the internals extensible while keeping the public API simple.

## Public API Functions for Loading YAML

The convenient entry points are implemented in [`src/parse.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/parse.cpp) and declared in [`include/yaml-cpp/parser.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/parser.h). Each function handles a specific source type:

- **`YAML::Load(std::istream&)`** – The core entry point that constructs a `Parser`, attaches a `NodeBuilder`, and invokes `HandleNextDocument` to return a single `Node`.
- **`YAML::Load(const std::string&)`** – Wraps the string in a `std::stringstream` and forwards to the stream overload.
- **`YAML::Load(const char*)`** – Identical to the string version for C‑string literals.
- **`YAML::LoadFile(const std::string&)`** – Opens an `std::ifstream`, throws `YAML::BadFile` on failure, and forwards to `Load(stream)`.
- **`YAML::LoadAll(std::istream&)`** – Parses multiple YAML documents from a single stream, looping `HandleNextDocument` until exhaustion and collecting each root node into a `std::vector<Node>`.
- **`YAML::LoadAllFromFile(const std::string&)`** – Combines file opening with multi‑document parsing.

These functions are defined at lines 12, 17, 22, 32, 50, and 65 of [`src/parse.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/parse.cpp) respectively.

## Parsing a Single Document from a File

For configuration files or single‑document inputs, use `YAML::LoadFile`. This function handles stream lifetime internally and throws `YAML::BadFile` if the file cannot be opened.

```cpp
#include <yaml-cpp/yaml.h>
#include <iostream>

int main() {
    try {
        YAML::Node config = YAML::LoadFile("config.yaml");
        std::cout << "Host: " << config["host"].as<std::string>() << "\n";
        std::cout << "Port: " << config["port"].as<int>() << "\n";
    } catch (const YAML::BadFile& e) {
        std::cerr << "Cannot open file: " << e.what() << "\n";
    } catch (const YAML::ParserException& e) {
        std::cerr << "YAML error: " << e.what() << "\n";
    }
}

```

## Parsing Multiple Documents from a String

YAML streams may contain multiple documents separated by `---`. The `YAML::LoadAll` family returns a `std::vector<YAML::Node>` containing each document’s root node.

```cpp
#include <yaml-cpp/yaml.h>
#include <iostream>

int main() {
    const char* yaml = R"(---
name: Alice
---
name: Bob
---)";

    std::vector<YAML::Node> docs = YAML::LoadAll(yaml);
    for (std::size_t i = 0; i < docs.size(); ++i) {
        std::cout << "Doc " << i << " name: " << docs[i]["name"].as<std::string>() << "\n";
    }
}

```

## Streaming Parsing from Standard Input

Because `YAML::Load` accepts any `std::istream&`, you can parse directly from `std::cin`, a `std::stringstream`, or a custom stream implementation without intermediate buffering.

```cpp
#include <yaml-cpp/yaml.h>
#include <iostream>

int main() {
    std::cout << "Enter YAML (Ctrl-D to finish):\n";
    YAML::Node root = YAML::Load(std::cin);
    
    if (root["greeting"]) {
        std::cout << "Greeting: " << root["greeting"].as<std::string>() << "\n";
    }
}

```

## Summary

- **High‑level convenience** – `YAML::Load`, `YAML::LoadFile`, and `YAML::LoadAll` in [`src/parse.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/parse.cpp) provide the primary interface for parsing YAML from files or input streams.
- **Internal architecture** – The library constructs a `Parser` (in [`src/parser.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/parser.cpp)) that drives a `Scanner` and `SingleDocParser`, feeding events to a `NodeBuilder` to produce the final `Node` tree defined in [`include/yaml-cpp/node/node.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/node/node.h).
- **Flexible input** – All public functions accept `std::istream&`, allowing seamless integration with files, strings, and standard input.
- **Error handling** – Expect `YAML::BadFile` for filesystem errors and `YAML::ParserException` for malformed YAML content.

## Frequently Asked Questions

### How do I parse YAML from a string instead of a file?

Use `YAML::Load(const std::string&)`. According to the implementation in [`src/parse.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/parse.cpp) (line 12), this overload creates a `std::stringstream` internally and forwards it to the core `Load(std::istream&)` function, so you do not need to manually wrap your string.

### What is the difference between `Load` and `LoadAll`?

`YAML::Load` parses exactly one document from the stream and returns a single `Node`, whereas `YAML::LoadAll` continues reading after document boundaries (`---`) and returns a `std::vector<Node>` containing every document found in the stream. The implementation in [`src/parse.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/parse.cpp) (lines 50–65) shows that `LoadAll` simply loops `HandleNextDocument` until the scanner reports no more content.

### Can I parse from a custom C++ stream class?

Yes. Because `YAML::Load` takes a `std::istream&` reference (as seen in [`src/parse.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/parse.cpp) line 22), any class inheriting from `std::istream`—including `std::stringstream`, `std::ifstream`, or your own custom implementation—works transparently with the parser.

### What exceptions should I catch when loading a file?

Catch `YAML::BadFile` (thrown in `LoadFile` at [`src/parse.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/parse.cpp) line 32 when the `std::ifstream` fails to open) and `YAML::ParserException` (thrown by the `Parser` or `SingleDocParser` when encountering invalid YAML syntax). Catching `std::exception` will also handle these cases, but specific catches allow more granular error reporting.