一个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