gpt4 book ai didi

c# - 请求分块加载我的文件的方向(只需要建议)

转载 作者:太空宇宙 更新时间:2023-11-03 16:44:54 25 4
gpt4 key购买 nike

过去几天,我一直在研究一种方法,可以在保存时将我的 xna 游戏的 1.44 亿个图 block 表示压缩到非常小的尺寸。成功完成后,我现在发现自己对如何从文件中分块取回它们感到困惑。

在我的文件中。

  1. 一个整数(使用 7BitEncodedInt 方法将其压缩为字节)
  2. 一个字节

压缩后的整数表示瓦片的数量,后面的字节决定瓦片的类型。这一切都很好,而且效果很好。最重要的是,它将文件大小平均缩小到仅 50mb。

问题是我目前正在读回整个文件。我从文件中得到这个。

  1. 每个图 block 的索引值(只是我抓取图 block 时的基本迭代)
  2. 每个图 block 的类型作为字节值
  3. 表示该图 block 纹理的字节值(这很难解释,但对每个图 block 而言都是必需的)

所有这一切的最终结果是我设法保存了文件并且只使用了大约 50mb。但是通过将整个东西加载回去,它在 ram 上扩展到近 1.5gigs。我真的不能再牺牲磁贴信息了。所以我需要一种方法来根据玩家位置只加载 map 的一部分。目标是在 100-200mb 范围内

我一直在研究文件的内存映射,使用四叉树,几乎所有我能找到的用于分块加载文件的东西。虽然这些选项看起来都不错,但我不确定哪个是最好的,或者如果考虑到这种情况,可能还有另一个更好的选项。所有这一切的另一个问题是,这些解决方案似乎都非常复杂(尤其是因为这是我第一次使用它们),虽然我不反对将自己投入到一些冗长的编码中,但我想知道它会做我想做的事事先需要它。

我的问题是,考虑到我在拉入文件时必须如何处理文件,以及需要根据玩家位置完成此操作的事实,最好的方法是什么?我只是在这里寻找一些方向。代码总是受欢迎的,但不是必需的。

最佳答案

您想在 Tile 类中使用固定长度的变量并实现如下内容:

这是一个集合类 (People) 的示例,它可以根据索引从序列化到文件中的集合中获取值。

Person 是 People 集合的基础类。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FileStreamDatabaseTest
{
class Program
{
static void Main(string[] args)
{
People.OpenCollection();
People.Test_WillOverwriteData();
People.CloseCollection();
Console.ReadLine();
}
}

public class Person
{
// define maxium variable sizes for serialisation
protected static int pMaxLength_FirstName = 64;
protected static int pMaxLength_Age = 10;
public static int MaxObjectSize
{
get
{
// return the sum of all the maxlegnth variables to define the entire object size for serialisation
return pMaxLength_FirstName + pMaxLength_Age;
}
}

// define each object that will be serialised as follows
protected string pFirstName;
public string Firstname
{
set
{
// ensure the new value is not over max variable size
if (value.Length > pMaxLength_FirstName)
throw new Exception("the length of the value is to long.");

pFirstName = value;
}
get
{
return pFirstName;
}
}
protected int pAge;
public int Age
{
get
{
return pAge;
}
set
{
pAge = value;
}
}

public byte[] Serialise()
{
// Output string builder
StringBuilder Output = new StringBuilder();

// Append firstname value
Output.Append(Firstname);

// Add extra spaces to end of string until max length is reached
if (Firstname.Length < pMaxLength_FirstName)
for (int i = Firstname.Length; i < pMaxLength_FirstName; i++)
Output.Append(" ");

// Append age value as string
Output.Append(Age.ToString());

// Add extra spaces to end of string until max length is reached
int AgeLength = Age.ToString().Length;
if (AgeLength < pMaxLength_Age)
for (int i = AgeLength; i < pMaxLength_Age; i++)
Output.Append(" ");

// Return the output string as bytes using ascii encoding
return System.Text.Encoding.ASCII.GetBytes(Output.ToString());
}

public void Deserialise(byte[] SerialisedData)
{
string Values = System.Text.Encoding.ASCII.GetString(SerialisedData);

pFirstName = Values.Substring(0, pMaxLength_FirstName).Trim();
pAge = int.Parse(Values.Substring(pMaxLength_FirstName, pMaxLength_Age).Trim());
}
}

public static class People
{
private static string tileDatasource = @"c:\test.dat";
private static System.IO.FileStream FileStream;

public static void OpenCollection()
{
FileStream = new System.IO.FileStream(tileDatasource, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite, System.IO.FileShare.None);
}

public static void CloseCollection()
{
FileStream.Close();
FileStream.Dispose();
FileStream = null;
}

public static void SaveCollection(Person[] People)
{
FileStream.SetLength(People.Length * Person.MaxObjectSize);
FileStream.Position = 0;

foreach (Person PersonToWrite in People)
{
// call serialise to get bytes
byte[] OutputBytes = PersonToWrite.Serialise();

// write the output buffer
// note: this will always be the same size as each variable should
// append spaces until its max size is reached
FileStream.Write(OutputBytes, 0, OutputBytes.Length);
}
}

public static Person GetValue(int Index)
{
// set the stream position to read the object by multiplying the requested index with the max object size
FileStream.Position = Index * Person.MaxObjectSize;

// read the data
byte[] InputBytes = new byte[Person.MaxObjectSize];
FileStream.Read(InputBytes, 0, Person.MaxObjectSize);

// deserialise
Person PersonToReturn = new Person();
PersonToReturn.Deserialise(InputBytes);

// retun the person
return PersonToReturn;
}

public static void Test_WillOverwriteData()
{
long StartTime;
long EndTime;
TimeSpan TimeTaken;

Console.WriteLine("-------------------------------------------------------------------");
Console.WriteLine("*** Creating 2,000,000 test people... ");
StartTime = DateTime.Now.Ticks;
Person[] People = new Person[2000000];
for (int i = 0; i < 2000000; i++)
{
People[i] = new Person();
People[i].Firstname = "TestName." + i;
People[i].Age = i;
}
EndTime = DateTime.Now.Ticks;
TimeTaken = new TimeSpan(EndTime - StartTime);
Console.WriteLine("-> Completed in " + TimeTaken.TotalSeconds + " seconds");

Console.WriteLine("-------------------------------------------------------------------");
Console.WriteLine("*** Serialising Collection to disk... ");
StartTime = DateTime.Now.Ticks;
SaveCollection(People);
EndTime = DateTime.Now.Ticks;
TimeTaken = new TimeSpan(EndTime - StartTime);
Console.WriteLine("-> Completed in " + TimeTaken.TotalSeconds + " seconds");

Console.WriteLine("-------------------------------------------------------------------");
Console.WriteLine("*** Redundancy Test... ");
StartTime = DateTime.Now.Ticks;
bool Parsed = true;
int FailedCount = 0;
for (int i = 0; i < 2000000; i++)
{
if (GetValue(i).Age != i)
{
Parsed = false;
FailedCount++;
}
}
EndTime = DateTime.Now.Ticks;
TimeTaken = new TimeSpan(EndTime - StartTime);
Console.WriteLine("-> " + (Parsed ? "PARSED" : "FAILED (" + FailedCount + " failed index's"));
Console.WriteLine("-> Completed in " + TimeTaken.TotalSeconds + " seconds");

Console.WriteLine("-------------------------------------------------------------------");
Console.WriteLine("*** Reading 10,000 index's at once... ");
StartTime = DateTime.Now.Ticks;
Person[] ChunkOfPeople = new Person[10000];
for (int i = 0; i < 10000; i++)
ChunkOfPeople[i] = GetValue(i);
EndTime = DateTime.Now.Ticks;
TimeTaken = new TimeSpan(EndTime - StartTime);
Console.WriteLine("-> Completed in " + TimeTaken.TotalSeconds + " seconds");


Console.WriteLine("-------------------------------------------------------------------");
Console.WriteLine("*** Reading 100,000 index's at once... ");
StartTime = DateTime.Now.Ticks;
ChunkOfPeople = new Person[100000];
for (int i = 0; i < 100000; i++)
ChunkOfPeople[i] = GetValue(i);
EndTime = DateTime.Now.Ticks;
TimeTaken = new TimeSpan(EndTime - StartTime);
Console.WriteLine("-> Completed in " + TimeTaken.TotalSeconds + " seconds");

Console.WriteLine("-------------------------------------------------------------------");
Console.WriteLine("*** Reading 1,000,000 index's at once... ");
StartTime = DateTime.Now.Ticks;
ChunkOfPeople = new Person[1000000];
for (int i = 0; i < 1000000; i++)
ChunkOfPeople[i] = GetValue(i);
EndTime = DateTime.Now.Ticks;
TimeTaken = new TimeSpan(EndTime - StartTime);
Console.WriteLine("-> Completed in " + TimeTaken.TotalSeconds + " seconds");
}
}
}

关于c# - 请求分块加载我的文件的方向(只需要建议),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6352816/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com