一个c#实现的文件操作的方法;改为java实现;由于本人开发经验不足,暂时无法自己完成,在此求教一下大佬!

这是代码和操作的文件链接:https://pan.baidu.com/s/1XWlI...
提取码:zyz4

using Xunit;

using System;

using System.Collections.Generic;

using System.IO;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using Newtonsoft.Json.Linq;

namespace TestProject1

{

public class UnitTest1

{

byte[] buffer;

int endPosition;

List<zpkMediaFileInfo> mediaFileInfos;

private string zpkFile = "";

private string saveToDirectory = "";

[Fact]

public void Test1()

{

string saveToDir = "D:\\data";

string zpkdir = "D:\\data\\401";

DirectoryInfo directoryInfo = new DirectoryInfo(zpkdir);

ExtractFiles(directoryInfo,saveToDir);

}

/// <summary>

///

/// </summary>

/// <param name="zpkdir">zpk文件所在的DirectoryInfo</param>

/// <param name="saveToDir">解压后保存的文件夹</param>

public void ExtractFiles(DirectoryInfo zpkdir, string saveToDir)

{

if (!Directory.Exists(zpkdir.FullName))

{

throw new FileNotFoundException(zpkdir.FullName);

}

int i = 0;

foreach (FileInfo file in zpkdir.GetFiles("*.zpk", SearchOption.AllDirectories))

{

ExtractFile(file.FullName, saveToDir);

}

}

public void ExtractFile(string zpkFile, string saveToDir)

{

try

{

this.saveToDirectory = saveToDir;

this.zpkFile = zpkFile;

initBufferVarieties(zpkFile);

writeMediaFiles();

}

catch (Exception ex)

{

}

}

#region 核心流程

//核心是得到mediaFileInfos,mediaFileInfos里有媒体文件的名称,在buffer里的起始位置和大小;

//得到信息后从文件里提取字节信息,保存;

//初始化变量

void initBufferVarieties(string zpkFile)

{

FileStream fs = new FileStream(zpkFile, FileMode.Open);

if (fs.Length < 10)

{

throw new FileLoadException("the file is empty");

}

this.buffer = new byte[fs.Length];

fs.Position = 0;

fs.Read(buffer, 0, buffer.Length);

this.endPosition = getEndPosition();

fs.Close();

this.mediaFileInfos = getMediaFiles();

}

void writeMediaFiles()

{

string folderName = getWordName(mediaFileInfos);

string dir = Path.Combine(this.saveToDirectory, folderName);

Directory.CreateDirectory(dir);

foreach (zpkMediaFileInfo media in mediaFileInfos)

{

string path = Path.Combine(dir, media.Name);

var bs = getBytes(media.StartPostion, media.StartPostion + media.Size);

File.WriteAllBytes(path, bs);

}

}

List<zpkMediaFileInfo> getMediaFiles()

{

//从zpk文件末尾得到包含的文件的列表;

var bs = getBytes(buffer, endPosition, buffer.Length);

string s = Encoding.ASCII.GetString(bs).Trim();

List<string> files = s.Split('\n').ToList();

//得到zpk里media文件的信息;

List<zpkMediaFileInfo> mediaFiles = new List<zpkMediaFileInfo>();

for (int i = 0; i < files.Count(); i++)

{

zpkMediaFileInfo media = new zpkMediaFileInfo();

media.Name = files[i];

int posLeftStart = endPosition - 3 * 16 * (files.Count() - i);

media.StartPostion = getTranslatePostion(posLeftStart);

int posLeftSize = posLeftStart + 1 * 16;

media.Size = getTranslatePostion(posLeftSize);

mediaFiles.Add(media);

}

return mediaFiles;

}

#endregion

#region 方法

/// <summary>

/// 从json文件里获取单词的名字;

/// </summary>

/// <param name="mediaFiles"></param>

/// <returns></returns>

string getWordName(List<zpkMediaFileInfo> mediaFiles)

{

string wordName = "";

var jsons = mediaFiles.Where(n => n.Name.EndsWith(".json"));

if (jsons.Count() == 0)

{

string msg = string.Format(@"{0} 不存在json文件", this.zpkFile);

throw new Exception(msg);

}

else

{

try

{

//获取json字符串

var json = jsons.First();

var bs = getBytes(json.StartPostion, json.StartPostion + json.Size);

string jsonStr = Encoding.UTF8.GetString(bs);

//获得word名

JObject j = JObject.Parse(jsonStr);

wordName = j["word"].ToString();

}

catch (Exception)

{

//throw;

}

}

return wordName;

// folderName = DateTime.Now.ToString("yyyyMMddHHmmff");

}

int getTranslatePostion(int pos)

{

int p = buffer[pos] + 16 * 16 * buffer[pos + 1] + 16 * 16 * 16 * 16 * buffer[pos + 2];

return p;

}

/// <summary>

/// 得到尾部的第一个字符的位置;

/// 尾部是文件列表;

/// </summary>

/// <returns></returns>

int getEndPosition()

{

const int LastLen = 16 * 20;

var bs = getBytes(buffer, buffer.Length - LastLen, buffer.Length);

bs = bs.Reverse().ToArray();

int i = getIndexOfSubArray(bs, "000000"); //得到的值是倒着从1数文件尾部的第一个字符的位置;

if (i < 0)

{

throw new Exception("获取文件列表错误");

}

return buffer.Length - i;

}

/// <summary>

/// 在十进制的数组bytes中找到16进制字符串hexString的位置;

/// </summary>

/// <param name="bytes"></param>

/// <param name="hexString">16进制的字符串</param>

/// <returns></returns>

int getIndexOfSubArray(byte[] bytes, string hexString)

{

var inBytes = Hex2Oec(hexString);

return getIndexOfSubArray(bytes, inBytes);

}

/// <summary>

/// 得到数组inBytes在数组bytes里出现的位置; inBytes是bytes的子串;

/// </summary>

/// <param name="bytes"></param>

/// <param name="inBytes"></param>

/// <returns></returns>

int getIndexOfSubArray(byte[] bytes, byte[] inBytes)

{

int comparePos = 0;

for (int i = 0; i < bytes.Length; i++)

{

if (comparePos > inBytes.Length - 1)

{

int pos = i - inBytes.Length;

return pos;

}

if (inBytes[comparePos] == bytes[i])

{

comparePos += 1;

}

else

{

comparePos = 0;

}

}

return -1;

}

/// <summary>

/// 把一串16进制数每两个一组,转换成int的数组;

/// </summary>

/// <param name="hex"></param>

/// <returns></returns>

byte[] Hex2Oec(string hex)

{

if (hex.Length % 2 == 1)

{

throw new ArgumentException();

}

List<byte> lstByte = new List<byte>();

for (int i = 0; i < hex.Length; i += 2)

{

var hs = hex.Substring(i, 2);

byte b = (byte)Convert.ToInt16(hs, 16);

lstByte.Add(b);

}

return lstByte.ToArray();

}

/// <summary>

///

/// </summary>

/// <param name="bs"></param>

/// <param name="start">开始位置,包含这个位置</param>

/// <param name="end">不包含结束位置的字符;</param>

/// <returns></returns>

byte[] getBytes(byte[] bs, int start, int end)

{

byte[] newbs = new byte[end - start];

int j = 0;

for (int i = start; i < end; i++)

{

newbs[j] = bs[i];

j++;

}

return newbs;

}

byte[] getBytes(int start, int end)

{

return getBytes(buffer, start, end);

}

#endregion

}

class zpkMediaFileInfo

{

public string Name { set; get; }

public int StartPostion { set; get; }

public int Size { set; get; }

}

}

以上是 一个c#实现的文件操作的方法;改为java实现;由于本人开发经验不足,暂时无法自己完成,在此求教一下大佬! 的全部内容, 来源链接: utcz.com/p/944256.html

回到顶部