我在存储信息时遇到一些问题。问题来了,因为在保存列表时,即使信息看起来很短,我也会得到很长的字符串。
让我们说我有100所房屋,我想节省每所房屋中有多少人。我用这个:
Houses.cs
[System.Serializable]
public class Houses
{
public int ID { get; set; }
public int PEOPLE { get; set; }
public Houses(int _ID, int _PEOPLE)
{
ID = _ID;
PEOPLE = _PEOPLE ;
}
}
然后在另一个脚本中我拥有
public List<Houses> HousesList = new List<Houses>();
void Awake()
{
HousesList.Add(new Houses(0,0));
//repeat until 100 (or more) I use a loop to initialize it
}
然后添加我说的人:
HousesList[3].PEOPLE+=5;
然后保存,我使用BinaryFormatter / MemoryStream的方式,但是即使列表中只有一个ID和一个人的值,结果序列化的字符串也包含4,000-5,000个字符。
要存储少量数据,我使用同一系统,但仅使用一个列表:
Houses.Add(new Houses(0,2,0,0,1)); // house 1, house 2... house 5
但是这样,即使有100个房屋,字符串也很短,但是却与这么多数字混淆。之后,如果我添加更多房屋,我可能会在保存/加载方面遇到问题。
有什么方法可以管理此类数据并将其保存在更短的字符串中?
谢谢。
答案 0 :(得分:3)
您甚至可以简单地将其保存为表格的每一行的行列表
id people
所以您有一个文件,例如
0 3
1 4
2 5
...
,稍后您可以通过
进行解析var lines = fileContent.Split('/n');
然后在每一行
var parts = line.Split(' ');
int id = int.TryParse(parts[0]) ? id : -1;
int people = int.TryParse(parts[1]) ? people : -1;
例如,在代码中
[Serializable]
public class House
{
public int Id;
public int People;
public House(int id, int people)
{
Id = id;
People = people;
}
}
List<House> Houses = new List<House>();
public void Save()
{
var stringBuilder = new StringBuilder();
foreach(var house in Houses)
{
stringBuilder.Append(house.Id).Append(' ').Append(house.People).Append('/n');
}
// Now use the file IO method of your choice e.g.
File.WriteAllText(filePath, stringBuilder.ToString(), Encoding.UTF8);
}
public void Load()
{
// clear current list
Houses.Clear();
// Use the file IO of choice e.g.
string readText = File.ReadAllText(path);
var lines = readText.Split('/n', StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
var parts = line.Split(' ');
// skip wrong formatted line
if(parts.Length != 2) continue;
int id = int.TryParse(parts[0]) ? id : -1;
int people = int.TryParse(parts[1]) ? people : -1;
if(id < 0 || people < 0) continue;
Houses.Add(new House(id, people));
}
}
现在您的房屋编号和人数都在这里。
字符串的长度取决于您的课程价值,但是会是类似的(对于100的huese,人数为> 9
和< 100
)
house IDs + seperator + people + /n
10+89*2 + 100 + 100 * 2 + 100
≈ 588 characters | bytes
答案 1 :(得分:2)
BinaryFormatter
因其高效的串行器而闻名。实际上,您真的真的不应该使用它;坦率地说。有很多已知的问题。
如果您很想念太空,protobuf可能是一个不错的选择;为此,protobuf约为596字节;在这种情况下,我使用的是protobuf-net:
596 bytes
100 items
95, 95
96, 96
97, 97
98, 98
99, 99
包含代码:
using ProtoBuf;
using System.Collections.Generic;
using System.IO;
using System.Linq;
static class P
{
static void Main()
{
var houses = new List<Houses>();
for (int i = 0; i < 100; i++)
houses.Add(new Houses(i, i));
using(var ms = new MemoryStream())
{
Serializer.Serialize(ms, houses);
System.Console.WriteLine($"{ms.Length} bytes");
ms.Position = 0;
var clone = Serializer.Deserialize<List<Houses>>(ms);
System.Console.WriteLine($"{clone.Count} items");
foreach(var item in clone.Skip(95))
{
System.Console.WriteLine($"{item.Id}, {item.People}");
}
}
}
}
[ProtoContract(SkipConstructor = true)]
public class Houses
{
[ProtoMember(1)]
public int Id { get; set; }
[ProtoMember(2)]
public int People { get; set; }
public Houses(int id, int people)
{
Id = id;
People = people;
}
}
答案 2 :(得分:1)
这是我尝试使用Json.Net + GZipStream
Json length: characters=2181, bytes=2181
gzipped.Length=437
class Program
{
public class Houses
{
public int Id { get; } // Btw. No need for setters
public int People { get; }
public Houses(int id, int people)
{
Id = id;
People = people;
}
}
static void Main(string[] args)
{
var houses = new List<Houses>();
for (int i = 0; i < 100; i++)
houses.Add(new Houses(i, i));
var json = Newtonsoft.Json.JsonConvert.SerializeObject(houses);
byte[] inputBytes = Encoding.UTF8.GetBytes(json);
Console.WriteLine($"Json length: characters={json.Length}, bytes={inputBytes.Length}");
byte[] gzipped;
using (var outputStream = new MemoryStream())
{
using (var gZipStream = new GZipStream(outputStream, CompressionMode.Compress))
{
gZipStream.Write(inputBytes, 0, inputBytes.Length);
}
gzipped = outputStream.ToArray();
}
Console.WriteLine($"gzipped.Length={gzipped.Length}");
}
}