简体   繁体   English

简单的二进制读写器代码不起作用

[英]Simple binary reader-writer code not working

MS VS 2010, XNA 4.0 MS VS 2010,XNA 4.0
So, I have a class Planet & it has Save and Load functions. 因此,我有一个Planet类,并且具有Save和Load函数。

public void SaveToFile(ContentManager content)
    {
        string path = content.RootDirectory + @"\Objects\Planets\" + this.name +@".planet"; 
        using (BinaryWriter bw = new BinaryWriter(File.Open(path, FileMode.Create)))
        {
            bw.Write(name);

            //sprite names
            bw.Write(planet.Sprite.Name); //"planet" is an animation.
            bw.Write(planet.HorFrames);   //and thats why it has a sprite
            bw.Write(planet.VerFrames);   //that has a name
            bw.Write((double)planet.FPS);

            bw.Write(asteroid1.Name);
            bw.Write(asteroid2.Name);
            bw.Write(asteroid3.Name);
            bw.Write(backgroundA.Name);

            //update related
            bw.Write((double)RSpeed);
            bw.Write((double)ASVariety);
            bw.Write((double)A1Chance);
            bw.Write((double)A2Chance);
            bw.Write((double)A3Chance);
            bw.Close();
        }
    }

public void LoadFromFile(ContentManager content, string name)
    {
        string path = content.RootDirectory + @"\Objects\Planets\" + name + @".planet";
        using (BinaryReader br = new BinaryReader(File.OpenRead(path)))
        {
            this.name = br.ReadString();
            this.planet = new Animation(Cont.Texture2D(br.ReadString()), br.ReadInt32(), br.ReadInt32(), (float)br.ReadDecimal(), true);
            this.asteroid1 = Cont.Texture2D(br.ReadString());
            this.asteroid2 = Cont.Texture2D(br.ReadString());
            this.asteroid3 = Cont.Texture2D(br.ReadString());
            this.backgroundA = Cont.Texture2D(br.ReadString());
            this.RSpeed = (float)br.ReadDouble();
            this.ASVariety = (float)br.ReadDouble();
            this.A1Chance = (float)br.ReadDouble();
            this.A2Chance = (float)br.ReadDouble();
            this.A3Chance = (float)br.ReadDouble();

            bposB = new Vector2(backgroundA.Width - 1, 0);
            bspd = new Vector2(-RSpeed / 8f, 0);

            pEngine1 = new ParticleEngine(MSTime, 40, new Vector2(20, -30), new Vector2(2, 1), asteroid1, new Color(100, 100, 100));
            pEngine1.Follow(new Vector2(-200, Game1.window_height / 2));

            pEngine2 = new ParticleEngine(MSTime * 3, 40, new Vector2(20, -30), new Vector2(2, 1), asteroid2, new Color(100, 100, 100));
            pEngine2.Follow(new Vector2(-200, Game1.window_height / 2));

            br.Close();
        }

Thats simple to understand, now isn't it? 这很容易理解,不是吗?
Now, when I try to load sprite for planet animation, I get an error, that says: 现在,当我尝试为星球动画加载精灵时,出现错误,提示:
"Value cannot be null. “值不能为空。
Parameter name: assetName" 参数名称:assetName”
and this is happening at the line 这正在发生
this.planet = new Animation(Cont.Texture2D(br.ReadString()), br.ReadInt32(), br.ReadInt32(), (float)br.ReadDecimal(), true); this.planet = new Animation(Cont.Texture2D(br.ReadString()),br.ReadInt32(),br.ReadInt32(),(float)br.ReadDecimal(),true);
Cont.Texture2D is a static functions that returns a Texture2D witch name is equal to the path it was loaded from, and it looks like this: Cont.Texture2D是一个静态函数,它返回Texture2D的女巫名称等于从其加载的路径,它看起来像这样:

public static Texture2D Texture2D(string path)
    {
        Texture2D sprite = content.Load<Texture2D>(path);
        sprite.Name = path;
        return sprite;
    }

So, when I'm saving it, it saves the right path. 因此,当我保存它时,它会保存正确的路径。 The test function looks like this: 测试函数如下所示:

private void testFunction()
    {
        /*
        p = new Planet("Mars", 
            new Animation(Cont.Texture2D("Sprites\\Planets\\mars"), 8, 2, 0.9f, true),
            Cont.Texture2D("Sprites\\Backgrounds\\space"),
            Cont.Texture2D("Sprites\\Asteroids\\small\\small 1"),
            Cont.Texture2D("Sprites\\Asteroids\\medium\\medium 1"),
            Cont.Texture2D("Sprites\\Asteroids\\big\\big 1"),
            100, 50, 40, 20, 40, 40);
        p.SaveToFile(Content);
        */
        p = new Planet(Content, "Mars");
        tests = p.ToString();
    }

"tests" is just a test string. “测试”只是一个测试字符串。 Now, I first execute the commented code, so it could save the file, and then i execute the uncommented code. 现在,我首先执行注释的代码,这样它可以保存文件,然后执行未注释的代码。 This planet constructor just calls the LoadFromFile function and nothing more. 这个Planet构造函数只调用LoadFromFile函数,仅此而已。 Also, I have the saved file in my content in my project. 另外,我的项目中的内容中有保存的文件。 I did say for that file to treat it as content (dont compile it). 我确实说过要将该文件视为内容(不要编译)。 So, the code "sees" the file, thats for shure, but it cant find the .png on the path that was read from the mars.planet. 因此,代码“看到”了文件,多数民众赞成在需要时,但它找不到从mars.planet读取的路径中的.png。 Is there maybe a misstake if i store 2 strings one after another, and then the reader cant see where is the end of the first one? 如果我一个接一个地存储2个字符串,那么读者可能看不到第一个字符串的结尾在哪里吗? Am I maybe saving it wrong? 我可能把它保存错了吗?

My goal is to have binary files that will be loaded and saved, and in them would be planets, rockets, maps, etc, that are collections of names and values that are needed for constructors of these classes. 我的目标是要拥有将要加载和保存的二进制文件,其中将包含行星,火箭,地图等,这些是这些类的构造函数所需的名称和值的集合。

Due to unnessesary complications with Binary writer-reader, I have decided to use Stream writer-reader. 由于Binary writer-reader不必要的复杂性,我决定使用Stream writer-reader。 Big thanks to @Blas Soriano & @Peter Duniho. 非常感谢@Blas Soriano和@Peter Duniho。

Binary writers seem not to be able to write 2 strings one after another in such way that binary reader can read them, at least not in my case. 二进制编写者似乎不能以二进制读取器可以读取它们的方式一个接一个地编写两个字符串,至少在我看来是这样。 I did try writing and reading 2 strings with binary wr in another project, and they seem to work fine there. 我确实尝试过在另一个项目中使用二进制wr编写和读取2个字符串,但它们似乎在这里可以正常工作。 I hope nobody expiriences this kind of thing that happened to me. 我希望没有人会喜欢我身上发生的这种事情。 Thanks again to Blas and Peter. 再次感谢布拉斯和彼得。

EDIT: 编辑:
It seems that my file that I included in Content of solution, "Mars.planet", in it's properties: Copy To Output, from 3 possible choices: Copy if newer, Never Copy, Always Copy, had selected the Copy Always, and that didnt allow changes to happen to that file, so, i DID change the file by saving it with my function, but, then I exit the game, so the file goes back to the old version (not really shure how), and that version is a realy old one, that didn't have all lines that I am in need now, so when I comment the saving code and uncomment the loading code, start the game, the function for loading would actually be loading the first version of the file (the version from the time when I included the file). 似乎我包含在解决方案的内容“ Mars.planet”中的文件的属性是:复制到输出,有3种可能的选择:如果较新则复制,从不复制,始终复制,选择了始终复制,并且不允许对该文件进行更改,因此,我通过使用函数保存文件来更改文件,但是,然后我退出了游戏,因此该文件返回到旧版本(不是很清楚如何),以及该版本是一个非常老的游戏,现在没有我需要的所有行,因此当我注释保存代码并取消注释正在加载的代码时,启动游戏,加载功能实际上将加载第一个版本的文件(我添加文件时的版本)。

It works now, but not because I am using the Stream wr, but because I changed the property of that file to:Do not copy. 它现在可以工作,但这不是因为我正在使用Stream wr,而是因为我将该文件的属性更改为:请勿复制。 I will be going back to Binary wr. 我将回到Binary wr。

In your testFunction() you create a new Planet and save it to a file without assigning the sprite name (and I guess it is not assigned in the Animation constructor), so when it is saved the sprite name will be null. 在您的testFunction()您将创建一个新的Planet并将其保存到文件中而不指定Sprite名称(我想它不是在Animation构造函数中分配的),因此,保存时Sprite名称将为null。 To avoid that, you need to assign the planet.Sprite.Name before saving it to a file. 为了避免这种情况,需要先将planet.Sprite.Name分配给文件。

private void testFunction()
{
    Animation planetAnimation = new Animation(Cont.Texture2D("Sprites\\Planets\\mars"));
    planetAnimation.Sprite.Name = "Sprites\\Planets\\mars";
    p = new Planet("Mars", 
        planetAnimation , 8, 2, 0.9f, true),
        Cont.Texture2D("Sprites\\Backgrounds\\space"),
        Cont.Texture2D("Sprites\\Asteroids\\small\\small 1"),
        Cont.Texture2D("Sprites\\Asteroids\\medium\\medium 1"),
        Cont.Texture2D("Sprites\\Asteroids\\big\\big 1"),
        100, 50, 40, 20, 40, 40);
    p.SaveToFile(Content);
    /*
    p = new Planet(Content, "Mars");
    tests = p.ToString();
    */
}

Instead of that, you could modify your Load and Save methods to avoid saving twice that string. 取而代之的是,您可以修改LoadSave方法以避免将字符串保存两次。 First delete or comment the line bw.Write(planet.Sprite.Name) in SaveToFile() : 首先删除或注释SaveToFile() bw.Write(planet.Sprite.Name) SaveToFile()

public void SaveToFile(ContentManager content)
{
    string path = content.RootDirectory + @"\Objects\Planets\" + this.name +@".planet"; 
    using (BinaryWriter bw = new BinaryWriter(File.Open(path, FileMode.Create)))
    {
        bw.Write(name);

        //sprite names
        //bw.Write(planet.Sprite.Name); //"planet" is an animation.
        bw.Write(planet.HorFrames);   //and thats why it has a sprite
        bw.Write(planet.VerFrames);   //that has a name
        bw.Write((double)planet.FPS);
...

Then change the LoadFromFile() to reuse the string: 然后更改LoadFromFile()以重复使用字符串:

public void LoadFromFile(ContentManager content, string name)
{
    string path = content.RootDirectory + @"\Objects\Planets\" + name + @".planet";
    using (BinaryReader br = new BinaryReader(File.OpenRead(path)))
    {
        this.name = br.ReadString();
        this.planet = new Animation(Cont.Texture2D(this.name), br.ReadInt32(), br.ReadInt32(), br.ReadDouble(), true);
        this.asteroid1 = Cont.Texture2D(br.ReadString());
        this.asteroid2 = Cont.Texture2D(br.ReadString());

Note that following cubrr suggestion, I replaced decimal to double while reading planet.FPS . 请注意,按照cubrr建议,我在读取planet.FPS将十进制替换为double。


EDIT: From your comment it seems you think the null string should be assigned by using the static method, but there are 2 different things here. 编辑:从您的评论看来,您认为应该使用静态方法来分配空字符串,但是这里有2种不同的方法。
First take a look at that name inside Cont.Texture2D() : 首先看看Cont.Texture2D()中的名称:

public static Texture2D Texture2D(string path)
{
    Texture2D sprite = content.Load<Texture2D>(path);
    sprite.Name = path;
    return sprite;
}

This name is Texture2D.Name 该名称是Texture2D.Name
Now take a look inside SaveToFile() : 现在看一下SaveToFile()

bw.Write(name);

//sprite names
bw.Write(planet.Sprite.Name); //"planet" is an animation.

Here we can see 2 different names, Planet.Name and Planet.Sprite.Name . 在这里,我们可以看到2个不同的名称, Planet.NamePlanet.Sprite.Name Where are you assigning that second name? 您在哪里分配该第二名? That's why I used planetAnimation.Sprite.Name = "Sprites\\\\Planets\\\\mars"; 这就是为什么我使用planetAnimation.Sprite.Name = "Sprites\\\\Planets\\\\mars"; .

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

相关问题 MSR Orleans - 如何使用并行读取创建读写器粒度 - MSR Orleans - How to create a reader-writer grain with parallel reads 二进制读取器和写入器同时打开? - Binary Reader and Writer open at same time? 在二进制读写器 C# 中使用编码有什么好处? - what are benefits of using Encoding in binary reader and writer C#? 对于字符串数据使用TextReader / Writer而不是Binary Reader / Writer有什么好处? - What is the benefit of using a TextReader/Writer instead of a Binary Reader/Writer for string data? 我想使用二进制读取器/写入器求和存储在两个文本文件中的值,但是当我运行代码时,它不显示输出,甚至不出现异常 - I want to sum the values stored in two textfiles using binary reader/writer ,but when i run the code it doesnt shows the output ,dont even exceptions 异步读写器锁定器 - Async reader/writer locker 流的优点/缺点[读/写器] - Pros/Cons of Stream[Reader/Writer] 使用带有多个读取器线程+编写器的Array - Using Array with multiple reader threads + writer 如何在 .NET 中平衡读写线程 - How to balance reader and writer threads in .NET 帮助理解.NET中的Reader / Writer模式 - Help understanding the Reader/Writer pattern in .NET
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM