简体   繁体   English

值已读取,或尝试从 Stream 读取时没有值

[英]Value already read, or no value when trying to read from a Stream

I've been trying this for a long time but it keeps giving me an error.我已经尝试了很长时间,但它一直给我一个错误。 I have an array of bytes that should represent a nbt document.我有一个应该代表 nbt 文档的字节数组。 I would like to convert this into a c# object with a library: fNbt.我想将其转换为带有库的 c# object:fNbt。

Here is my code:这是我的代码:

byte[] buffer = Convert.FromBase64String(value);
byte[] decompressed;

using (var inputStream = new MemoryStream(buffer))
{
    using var outputStream = new MemoryStream();

    using (var gzip = new GZipStream(inputStream, CompressionMode.Decompress, leaveOpen: true))
    {
        gzip.CopyTo(outputStream);
    }

    fNbt.NbtReader reader = new fNbt.NbtReader(outputStream, true);
    var output = reader.ReadValueAs<AuctionItem>(); //Error: Value already read, or no value to read.
    return output;
}

When I try this, it works:当我尝试这个时,它有效:

            decompressed = outputStream.ToArray();
            outputStream.Seek(0, SeekOrigin.Begin);
            outputStream.Read(new byte[1000], 0, decompressed.Count() - 1);

But when I try this, it doesn't:但是当我尝试这个时,它不会:

            outputStream.Seek(0, SeekOrigin.Begin);
            fNbt.NbtReader reader = new fNbt.NbtReader(outputStream, true);
            reader.ReadValueAs<AuctionItem>();

NbtReader , like most stream readers, begins reading from the current position of whatever stream you give it. NbtReader ,像大多数 stream 阅读器一样,从您给它的任何 stream 的当前position 开始读取。 Since you're just done writing to outputStream , then that position is the stream's end.由于您刚刚完成了对outputStream的写入,因此 position 是流的结束。 Which means at that point there's nothing to be read.这意味着在这一点上没有什么可读的。

The solution is to seek the outputStream back to the beginning before reading from it:解决方案是在读取outputStream之前将outputStream返回到开头:

outputStream.Seek(0, SeekOrigin.Begin); // <-- seek to the beginning    

// Do the read
fNbt.NbtReader reader = new fNbt.NbtReader(outputStream, true);
var output = reader.ReadValueAs<AuctionItem>(); // No error anymore
return output;

The solution is as follows.解决方法如下。 NbtReader.ReadValueAs does not consider a nbtCompound or nbtList as value. NbtReader.ReadValueAs 不将 nbtCompound 或 nbtList 视为值。 I made this little reader but it is not done yet (I will update the code once it is done).我做了这个小阅读器,但还没有完成(一旦完成,我将更新代码)。

    public static T ReadValueAs<T>(string value) where T: new()
    {
        byte[] buffer = Convert.FromBase64String(value);

        using (var inputStream = new MemoryStream(buffer))
        {
            using var outputStream = new MemoryStream();

            using (var gzip = new GZipStream(inputStream, CompressionMode.Decompress, leaveOpen: true))
            {
                gzip.CopyTo(outputStream);
            }
            outputStream.Seek(0, SeekOrigin.Begin);

            return new EasyNbt.NbtReader(outputStream).ReadValueAs<T>();
        }
    }

This is the NbtReader:这是 NbtReader:

    private MemoryStream MemStream { get; set; }

    public NbtReader(MemoryStream memStream)
    {
        MemStream = memStream;
    }

    public T ReadValueAs<T>() where T: new()
    {
        return ReadTagAs<T>(new fNbt.NbtReader(MemStream, true).ReadAsTag());
    }

    private T ReadTagAs<T>(fNbt.NbtTag nbtTag)
    {
        //Reads to the root and adds to T...
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM