简单的二进制读写器代码无效

时间:2015-06-20 23:51:58

标签: c# file xna binaryreader binarywriter

MS VS 2010,XNA 4.0
所以,我有一个星球& amp;它具有保存和加载功能。

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();
        }

这很容易理解,现在不是吗? 现在,当我尝试为行星动画加载精灵时,我收到一个错误,即: “价值不能无效 参数名称:assetName“
这发生在线路上 this.planet = new Animation(Cont.Texture2D(br.ReadString()),br.ReadInt32(),br.ReadInt32(),(float)br.ReadDecimal(),true);
Cont.Texture2D是一个静态函数,它返回一个Texture2D女巫名称等于它的加载路径,它看起来像这样:

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

所以,当我保存它时,它会保存正确的路径。测试功能如下所示:

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”只是一个测试字符串。现在,我首先执行注释代码,因此它可以保存文件,然后执行未注释的代码。这个行星构造函数只调用LoadFromFile函数而已。另外,我在项目中的内容中保存了文件。我确实说过该文件将其视为内容(不要编译它)。所以,代码“看到”文件,那是为了shure,但是它无法在从mars.planet读取的路径上找到.png。如果我一个接一个地存储2个字符串,那么可能有一个错误,然后读者无法看到第一个字符串的结尾在哪里?我可能保存错了吗?

我的目标是拥有将被加载和保存的二进制文件,其中包括行星,火箭,地图等,这些是这些类的构造函数所需的名称和值的集合。

2 个答案:

答案 0 :(得分:1)

由于Binary writer-reader的复杂性,我决定使用Stream writer-reader。非常感谢@Blas Soriano&amp; @Peter Duniho。

二进制编写器似乎无法一个接一个地编写2个字符串,二进制阅读器可以读取它们,至少在我的情况下不是这样。我确实尝试在另一个项目中用二进制w-r编写和读取2个字符串,它们似乎在那里工作正常。我希望没有人能够解释发生在我身上的这种事情。再次感谢Blas和Peter。

编辑:
我的文件似乎包含在解决方案的内容中,&#34; Mars.planet&#34;,在它的属性中:复制到输出,来自3种可能的选择:复制如果更新,从不复制,总是复制,选择了复制始终,并且不允许对该文件进行更改,因此,我DID通过使用我的功能保存它来更改文件,但是,然后我退出游戏,所以文件回到了原来的版本(并不是真的很好),那个版本是一个真正的版本,现在还没有我需要的所有行,所以当我注释保存代码并取消注释加载代码,启动游戏,加载功能实际上是加载文件的第一个版本(从我加入文件时的版本)。

它现在工作,但不是因为我使用Stream wr,而是因为我将该文件的属性更改为:不要复制。我将回到Binary w-r。

答案 1 :(得分:0)

在你的procedure TMyAdapter.DataSourceDataChange(Sender: TObject; Field: TField); var Enabled: Boolean; begin Enabled := FModel.DataSet['enabled'].AsBoolean; FView.Label1.Enabled := Enabled; FView.DBEdit1.Enabled := Enabled; FView.Label2.Enabled := Enabled; FView.DBEdit2.Enabled := Enabled; FView.Label3.Enabled := Enabled; FView.DBEdit3.Enabled := Enabled; FView.Label4.Enabled := Enabled; FView.DBEdit4.Enabled := Enabled; end; 中创建一个新星球,并将其保存到文件中而不指定精灵名称(我猜它没有在动画构造函数中指定),所以当它保​​存时,精灵名称将是空值。 为避免这种情况,您需要在将planet.Sprite.Name保存到文件之前指定它。

testFunction()

除此之外,您可以修改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(); */ } Load方法,以避免保存两次该字符串。 首先删除或评论Save中的行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); ... 以重用字符串:

LoadFromFile()

请注意,在cubrr建议之后,我在阅读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()); 时将十进制替换为双倍。

编辑:您的评论似乎认为应该使用静态方法分配空字符串,但这里有两个不同的东西。
首先看一下planet.FPS中的名字:

Cont.Texture2D()

此名称为Texture2D.Name
现在来看看public static Texture2D Texture2D(string path) { Texture2D sprite = content.Load<Texture2D>(path); sprite.Name = path; return sprite; }

SaveToFile()

在这里,我们可以看到两个不同的名称,bw.Write(name); //sprite names bw.Write(planet.Sprite.Name); //"planet" is an animation. Planet.Name。 你在哪里分配第二个名字?这就是我使用Planet.Sprite.Name的原因。