Skip to content

Reading

Eric Freed edited this page Aug 25, 2021 · 2 revisions

SharpNBT is capable of reading multiple flavors or NBT (see Protocols page), but it will need a minimal amount of information ahead of time to know about the source data to know how it should be interpreted.

TagReader Class

The TagReader class is the heart and soul of parsing a data stream. It only requires a base Stream object and flag indicating the data type to begin parsing.

using Stream stream = File.OpenRead("/path/to/file.nbt");
using TagReader reader = new TagReader(stream, FormatOptions.BigEndian);

Once created, you are ready to start parsing. For the majority of users, there is only one method that is pertinent: ReadTag and its asynchronous counterpart ReadTagAsync. This will read the next tag in the stream, which will in nearly all cases be a CompoundTag, with the sole exception of Bedrock editions occasionally using a ListTag. Both of these types share the common ancestor TagContainer, so it is always safe to cast the top-level tag to this type regardless of Minecraft version. When using Java-compatible data, it is always safe to assume the top-level tag is a CompoundTag.

TagContainer topLevel = (TagContainer) reader.ReadTag();

The above function return a generic Tag instance, but if the tag type is known ahead of time, you can use the shorthand read function to return it as the proper type.

CompoundTag compoundTag = reader.ReadTag<CompoundTag>();
CompoundTag compoundTag = await reader.ReadTagAsync<CompoundTag>();

There are numerous other methods available for reading each individual type of tag, but is very important to keep in mind the difference in where the current pointer in the stream is positioned. Using ReadTag assumes that the first byte indicating the type is still unread, while the individual tag read methods (i.e. ReadByteArray, ReadList, etc.) assume that the first byte has already been consumed and the pointer is positioned at the beginning of the payload. Keep this mind if you decide to inject any functionality into the parsing process through the use of callbacks or manual parsing.

Callbacks

There are two callback events that are available for subscribers: TagRead and TagEncountered.

TagRead

Called whenever the TagReader has completed parsing a tag from the stream. The parsed Tag and TagType are supplied in the arguments.

TagEncountered

Called when a tag is encountered in the stream, after only reading the first byte to determine the type. The arguments provide properties for the TagType and the underlying Stream itself. These arguments derive from HandledEventArgs, and give an opportunity for subscribers to fully take over the parsing process if needed. The only important guideline to follow is that the stream needs to be properly positioned depending on whether the tag was handled or not. When not handled, the stream position should not be moved, and when it is handled, the tag payload should be completely consumed.

Compression

Compression is not handled by the TagReader class, it is the responsibility of higher-level abstractions to pass in the proper decompression stream during initialization. As the TagReader is designed to be able to read from non-seekable streams (i.e. packets over a network stream), it is unable to assume that it is positioned at the start of a stream or attempt to detect compression.

Files

The static NbtFile class provides various methods for simplifying reading NBT files into a single invocation, including automatically detecting and handling compression.

CompoundTag tag = NbtFile.Read("/path/to/file.nbt", FormatOptions.Java);

As with other relevant methods in SharpNBT, there is an asynchronous counterpart:

var compoundTag = await NbtFile.ReadAsync("/path/to/file.nbt", FormatOptions.Java);

That's all there is to it, essentially the analog of the File.ReadAllText function found in System.IO, but for NBT data instead of text. If you wish to retrieve the data as a TagReader instance, but not consume the stream, the OpenRead function is also available:

using TagReader reader = NbtFile.OpenRead("/path/to/file.nbt", FormatOptions.BedrockFile);
Clone this wiki locally