-
Notifications
You must be signed in to change notification settings - Fork 57
/
Copy pathMetadataFile.cs
138 lines (114 loc) · 5.02 KB
/
MetadataFile.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace MetaDataStringEditor {
class MetadataFile : IDisposable {
public BinaryReader reader;
private uint stringLiteralOffset;
private uint stringLiteralCount;
private long DataInfoPosition;
private uint stringLiteralDataOffset;
private uint stringLiteralDataCount;
private List<StringLiteral> stringLiterals = new List<StringLiteral>();
public List<byte[]> strBytes = new List<byte[]>();
public MetadataFile(string fullName) {
reader = new BinaryReader(File.OpenRead(fullName));
// 读取文件
ReadHeader();
// 读取字符串
ReadLiteral();
ReadStrByte();
Logger.I("基础读取完成");
}
private void ReadHeader() {
Logger.I("读取头部");
uint vansity = reader.ReadUInt32();
if (vansity != 0xFAB11BAF) {
throw new Exception("标志检查不通过");
}
int version = reader.ReadInt32();
stringLiteralOffset = reader.ReadUInt32(); // 列表区的位置,后面不会改了
stringLiteralCount = reader.ReadUInt32(); // 列表区的大小,后面不会改了
DataInfoPosition = reader.BaseStream.Position; // 记一下当前位置,后面要用
stringLiteralDataOffset = reader.ReadUInt32(); // 数据区的位置,可能要改
stringLiteralDataCount = reader.ReadUInt32(); // 数据区的长度,可能要改
}
private void ReadLiteral() {
Logger.I("读取Literal");
ProgressBar.SetMax((int)stringLiteralCount / 8);
reader.BaseStream.Position = stringLiteralOffset;
for (int i = 0; i < stringLiteralCount / 8; i++) {
stringLiterals.Add(new StringLiteral {
Length = reader.ReadUInt32(),
Offset = reader.ReadUInt32()
});
ProgressBar.Report();
}
}
private void ReadStrByte() {
Logger.I("读取字符串的Bytes");
ProgressBar.SetMax(stringLiterals.Count);
for (int i = 0; i < stringLiterals.Count; i++) {
reader.BaseStream.Position = stringLiteralDataOffset + stringLiterals[i].Offset;
strBytes.Add(reader.ReadBytes((int)stringLiterals[i].Length));
ProgressBar.Report();
}
}
public void WriteToNewFile(string fileName) {
BinaryWriter writer = new BinaryWriter(File.Create(fileName));
// 先全部复制过去
reader.BaseStream.Position = 0;
reader.BaseStream.CopyTo(writer.BaseStream);
// 更新Literal
Logger.I("更新Literal");
ProgressBar.SetMax(stringLiterals.Count);
writer.BaseStream.Position = stringLiteralOffset;
uint count = 0;
for (int i = 0; i < stringLiterals.Count; i++) {
stringLiterals[i].Offset = count;
stringLiterals[i].Length = (uint)strBytes[i].Length;
writer.Write(stringLiterals[i].Length);
writer.Write(stringLiterals[i].Offset);
count += stringLiterals[i].Length;
ProgressBar.Report();
}
// 进行一次对齐,不确定是否一定需要,但是Unity是做了,所以还是补上为好
var tmp = (stringLiteralDataOffset + count) % 4;
if (tmp != 0) count += 4 - tmp;
// 检查是否够空间放置
if (count > stringLiteralDataCount) {
// 检查数据区后面还有没有别的数据,没有就可以直接延长数据区
if (stringLiteralDataOffset + stringLiteralDataCount < writer.BaseStream.Length) {
// 原有空间不够放,也不能直接延长,所以整体挪到文件尾
stringLiteralDataOffset = (uint)writer.BaseStream.Length;
}
}
stringLiteralDataCount = count;
// 写入string
Logger.I("更新String");
ProgressBar.SetMax(strBytes.Count);
writer.BaseStream.Position = stringLiteralDataOffset;
for (int i = 0; i < strBytes.Count; i++) {
writer.Write(strBytes[i]);
ProgressBar.Report();
}
// 更新头部
Logger.I("更新头部");
writer.BaseStream.Position = DataInfoPosition;
writer.Write(stringLiteralDataOffset);
writer.Write(stringLiteralDataCount);
Logger.I("更新完成");
writer.Close();
}
public void Dispose() {
reader?.Dispose();
}
public class StringLiteral {
public uint Length;
public uint Offset;
}
}
}