zxl
/
CTT
forked from Cal/CTT
1
0
Fork 0
CTT/Unity/Assets/Model/XAssetRuntime/Core/VDisk.cs

224 lines
5.4 KiB
C#
Raw Normal View History

2021-04-08 20:09:59 +08:00
//
// VDisk.cs
//
// Author:
// fjy <jiyuan.feng@live.com>
//
// Copyright (c) 2020 fjy
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using UnityEngine;
namespace libx
{
public class VFile
{
public string hash { get; set; }
public long id { get; set; }
public long len { get; set; }
public string name { get; set; }
public long offset { get; set; }
public VFile ()
{
offset = -1;
}
public void Serialize (BinaryWriter writer)
{
writer.Write (name);
writer.Write (len);
writer.Write (hash);
}
public void Deserialize (BinaryReader reader)
{
name = reader.ReadString ();
len = reader.ReadInt64 ();
hash = reader.ReadString ();
}
}
public class VDisk
{
private readonly byte[] _buffers = new byte[1024 * 4];
private readonly Dictionary<string, VFile> _data = new Dictionary<string, VFile> ();
private readonly List<VFile> _files = new List<VFile>();
public List<VFile> files { get { return _files; }}
public string name { get; set; }
private long _pos;
private long _len;
public VDisk ()
{
}
public bool Exists ()
{
return files.Count > 0;
}
private void AddFile (VFile file)
{
_data [file.name] = file;
files.Add (file);
}
public void AddFile (string path, long len, string hash)
{
2021-04-11 19:50:39 +08:00
VFile file = new VFile{ name = path, len = len, hash = hash };
2021-04-08 20:09:59 +08:00
AddFile (file);
}
private void WriteFile (string path, BinaryWriter writer)
{
2021-04-11 19:50:39 +08:00
using (FileStream fs = File.OpenRead (path)) {
long len = fs.Length;
2021-04-08 20:09:59 +08:00
WriteStream (len, fs, writer);
}
}
private void WriteStream (long len, Stream stream, BinaryWriter writer)
{
2021-04-11 19:50:39 +08:00
long count = 0L;
2021-04-08 20:09:59 +08:00
while (count < len) {
2021-04-11 19:50:39 +08:00
int read = (int)Math.Min (len - count, _buffers.Length);
2021-04-08 20:09:59 +08:00
stream.Read (_buffers, 0, read);
writer.Write (_buffers, 0, read);
count += read;
}
}
public bool Load (string path)
{
if (!File.Exists (path))
return false;
Clear ();
name = path;
2021-04-11 19:50:39 +08:00
using (BinaryReader reader = new BinaryReader (File.OpenRead (path))) {
int count = reader.ReadInt32 ();
for (int i = 0; i < count; i++) {
VFile file = new VFile { id = i };
2021-04-08 20:09:59 +08:00
file.Deserialize (reader);
AddFile (file);
}
_pos = reader.BaseStream.Position;
}
Reindex ();
return true;
}
public void Reindex ()
{
_len = 0L;
2021-04-11 19:50:39 +08:00
for (int i = 0; i < files.Count; i++) {
VFile file = files [i];
2021-04-08 20:09:59 +08:00
file.offset = _pos + _len;
_len += file.len;
}
}
public VFile GetFile (string path, string hash)
{
2021-04-11 19:50:39 +08:00
string key = Path.GetFileName (path);
2021-04-08 20:09:59 +08:00
VFile file;
_data.TryGetValue (key, out file);
return file;
}
public void Update(string dataPath, List<VFile> newFiles, List<VFile> saveFiles)
{
2021-04-11 19:50:39 +08:00
string dir = Path.GetDirectoryName(dataPath);
using (FileStream stream = File.OpenRead(dataPath))
2021-04-08 20:09:59 +08:00
{
2021-04-11 19:50:39 +08:00
foreach (VFile item in saveFiles)
2021-04-08 20:09:59 +08:00
{
2021-04-11 19:50:39 +08:00
string path = string.Format("{0}/{1}", dir, item.name);
2021-04-08 20:09:59 +08:00
if (File.Exists(path)) { continue; }
stream.Seek(item.offset, SeekOrigin.Begin);
2021-04-11 19:50:39 +08:00
using (FileStream fs = File.OpenWrite(path))
2021-04-08 20:09:59 +08:00
{
2021-04-11 19:50:39 +08:00
long count = 0L;
long len = item.len;
2021-04-08 20:09:59 +08:00
while (count < len)
{
2021-04-11 19:50:39 +08:00
int read = (int) Math.Min(len - count, _buffers.Length);
2021-04-08 20:09:59 +08:00
stream.Read(_buffers, 0, read);
fs.Write(_buffers, 0, read);
count += read;
}
}
newFiles.Add(item);
}
}
if (File.Exists(dataPath))
{
File.Delete(dataPath);
}
2021-04-11 19:50:39 +08:00
using (FileStream stream = File.OpenWrite (dataPath)) {
BinaryWriter writer = new BinaryWriter (stream);
2021-04-08 20:09:59 +08:00
writer.Write (newFiles.Count);
2021-04-11 19:50:39 +08:00
foreach (VFile item in newFiles) {
2021-04-08 20:09:59 +08:00
item.Serialize (writer);
}
2021-04-11 19:50:39 +08:00
foreach (VFile item in newFiles) {
string path = string.Format("{0}/{1}", dir, item.name);
2021-04-08 20:09:59 +08:00
WriteFile (path, writer);
File.Delete (path);
Debug.Log ("Delete:" + path);
}
}
}
public void Save ()
{
2021-04-11 19:50:39 +08:00
string dir = Path.GetDirectoryName (name);
using (FileStream stream = File.OpenWrite (name)) {
BinaryWriter writer = new BinaryWriter (stream);
2021-04-08 20:09:59 +08:00
writer.Write (files.Count);
2021-04-11 19:50:39 +08:00
foreach (VFile item in files) {
2021-04-08 20:09:59 +08:00
item.Serialize (writer);
}
2021-04-11 19:50:39 +08:00
foreach (VFile item in files) {
string path = dir + "/" + item.name;
2021-04-08 20:09:59 +08:00
WriteFile (path, writer);
}
}
}
public void Clear ()
{
_data.Clear ();
files.Clear ();
}
}
}