我的问题如下......
我有一个纹理文件,它不能用世界上的任何纹理编辑器打开,该文件包含例如100个纹理。获取这些纹理的唯一方法是使用十六进制编辑器(例如Hex Workshop)打开文件并找到“GBIX”字符串。当你找到一个“GBIX”字符串,你开始从那里复制到另一个GBIX的开头,你创建一个新文件,粘贴它,保存为PVR,你有纹理。但是你需要做100次,因为文件有100“GBIX”字符串(100个纹理)。嗯,现在,我在编程方面有一些小技巧,特别是在C#中,但我不知道如何创建一个程序,从字符串复制到字符串,然后将其保存在新文件中。
答案 0 :(得分:1)
在C中,这将是非常重要的:
strstr()
查找GBIX
模式我想在高级语言中会更容易。 :)
你的问题是什么?
答案 1 :(得分:1)
你能用C编程吗? 然后做一些事情
1.open the file using `fopen()` in binary mode.
2.use a loop upto the end of file and search for the string what you want (strstr() to look for the GBIX pattern)-copied from unwind
3.Then after finding each pattern get the position of the file pointer using ftell() and store it to a array of 100 integer(as 100 of texture you have ).
4.Then go to the first byte of file by using fseek().
5.Now you can use your array to find the location and read the whole data up to the next array element (do it in a loop upto 100 times).
6.then store this data or write it to another file(open a file in append mode and write there).
我觉得有点棘手但是使用这个算法并从互联网上搜索代码,你一定能做到这一点。
答案 2 :(得分:0)
我认为此代码示例可能会对您有所帮助。它显示了如何为您解析文件。您需要做的就是创建一个新文件..
using System;
using System.IO;
using Extensions;
using System.Drawing;
/* Archive Module */
namespace puyo_tools
{
public class Images
{
/* Image format */
private ImageClass Converter = null;
public GraphicFormat Format = GraphicFormat.NULL;
private Stream Data = null;
private Bitmap imageData = null;
public string ImageName = null;
private string FileExt = null;
/* Image Object for unpacking */
public Images(Stream dataStream, string dataFilename)
{
/* Set up our image information */
Data = dataStream;
ImageInformation(ref Data, out Format, out Converter, out ImageName, out FileExt);
}
/* Unpack image */
public Bitmap Unpack()
{
return Converter.Unpack(ref Data);
}
public Bitmap Unpack(Stream palette)
{
return Converter.Unpack(ref Data, palette);
}
/* Pack image */
public Stream Pack()
{
return Converter.Pack(ref imageData);
}
/* Output Directory */
public string OutputDirectory
{
get
{
return (ImageName == null ? null : ImageName + " Converted");
}
}
/* File Extension */
public string FileExtension
{
get
{
return (FileExt == null ? String.Empty : FileExt);
}
}
/* Get image information */
private void ImageInformation(ref Stream data, out GraphicFormat format, out ImageClass converter, out string name, out string ext)
{
try
{
/* Let's check for image formats based on the 12 byte headers first */
switch (data.ReadString(0x0, 12, false))
{
case GraphicHeader.GIM: // GIM (Big Endian)
case GraphicHeader.MIG: // GIM (Little Endian)
format = GraphicFormat.GIM;
converter = new GIM();
name = "GIM";
ext = ".gim";
return;
}
/* Ok, do special checks now */
/* PVR file */
if ((data.ReadString(0x0, 4) == GraphicHeader.GBIX && data.ReadString(0x10, 4) == GraphicHeader.PVRT && data.ReadByte(0x19) < 64) ||
(data.ReadString(0x0, 4) == GraphicHeader.PVRT && data.ReadByte(0x9) < 64))
{
format = GraphicFormat.PVR;
//converter = new PVR();
converter = null;
name = "PVR";
ext = ".pvr";
return;
}
/* GVR File */
if ((data.ReadString(0x0, 4) == GraphicHeader.GBIX && data.ReadString(0x10, 4) == GraphicHeader.GVRT) ||
(data.ReadString(0x0, 4) == GraphicHeader.GCIX && data.ReadString(0x10, 4) == GraphicHeader.GVRT) ||
(data.ReadString(0x0, 4) == GraphicHeader.GVRT))
{
format = GraphicFormat.GVR;
converter = new GVR();
name = "GVR";
ext = ".gvr";
return;
}
/* SVR File */
if ((data.ReadString(0x0, 4) == GraphicHeader.GBIX && data.ReadString(0x10, 4) == GraphicHeader.PVRT && data.ReadByte(0x19) > 64) ||
(data.ReadString(0x0, 4) == GraphicHeader.PVRT && data.ReadByte(0x9) > 64))
{
format = GraphicFormat.SVR;
converter = new SVR();
name = "SVR";
ext = ".svr";
return;
}
/* GMP File */
if (data.ReadString(0x0, 8, false) == "GMP-200\x00")
{
format = GraphicFormat.GMP;
converter = new GMP();
name = "GMP";
ext = ".gmp";
return;
}
/* Unknown or unsupported compression */
throw new GraphicFormatNotSupported();
}
catch (GraphicFormatNotSupported)
{
/* Unknown or unsupported image format */
format = GraphicFormat.NULL;
converter = null;
name = null;
ext = null;
return;
}
catch
{
/* An error occured. */
format = GraphicFormat.NULL;
converter = null;
name = null;
ext = null;
return;
}
}
/* Image Information */
public class Information
{
public string Name = null;
public string Ext = null;
public string Filter = null;
public bool Unpack = false;
public bool Pack = false;
public Information(string name, bool unpack, bool pack, string ext, string filter)
{
Name = name;
Ext = ext;
Filter = filter;
Unpack = unpack;
Pack = pack;
}
}
}
/* Image Format */
public enum GraphicFormat : byte
{
NULL,
GIM,
GMP,
GVR,
PVR,
SVR,
}
/* Image Header */
public static class GraphicHeader
{
public const string
GBIX = "GBIX",
GCIX = "GCIX",
GIM = ".GIM1.00\x00PSP",
GMP = "GMP-200\x00",
GVRT = "GVRT",
MIG = "MIG.00.1PSP\x00",
PVRT = "PVRT";
}
public abstract class ImageClass
{
/* Image Functions */
public abstract Bitmap Unpack(ref Stream data); // Unpack image
public abstract Stream Pack(ref Bitmap data); // Pack Image
public abstract bool Check(ref Stream data); // Check Image
public abstract Images.Information Information(); // Image Information
public virtual Bitmap Unpack(ref Stream data, Stream palette) // Unpack image (with external palette file)
{
return null;
}
}
}
答案 3 :(得分:0)
你说你使用过C#。这应该会让你大致了解如何在C#中做到这一点,尽管我自己没有测试过它。
在你开始之前,你的档案有多大?如果它完全适合内存,最简单的方法是使用File.ReadAllBytes
,它将整个文件读入一个很大的字节数组。 (如果你的文件大小为千兆字节,你将无法一次性加载它。如果是这种情况,有更多高级方法来读取文件,但我不会继续那些。)
您可以使用File.ReadAllBytes
来读取文件,Array.IndexOf
在其中搜索字节“G”,并使用正常的数组索引来检查其他字母。当您找到它们时,可以使用Array.Copy
复制出一大块数组,并使用File.WriteAllBytes
将其保存到文件中。
您的问题并不完全清楚文件的格式。根据您的描述,我认为它是这样的:
HEADERBYTESblahblahblahGBIXcontentcontentcontentGBIXmorecontentGBIXyetmorecontent
并且您希望将其丢弃:
HEADERBYTESblahblahblah
和要创建的三个单独文件:
GBIXcontentcontentcontent
GBIXmorecontent
GBIXyetmorecontent
所以我假设在第一个“GBIX”之前可能有文本并且你想忽略它,从最后一个“GBIX”到文件末尾的文本是你想要提取的正确纹理,没有任何事情发生在它之后我还假设字符“GBIX”永远不会出现在其中一个纹理的中间 - 如果它们那么你将需要使用能够真正理解文件格式的东西。
using System;
using System.IO;
public class Program
{
public static void WriteFile(int aFileIndex, byte[] sourceBytes, int firstByteIndex, int byteCount)
{
string filename = String.Format("output{0}.pvr", aFileIndex);
byte[] outputBytes = new byte[byteCount];
Array.Copy(sourceBytes, firstByteIndex, outputBytes, 0, byteCount);
File.WriteAllBytes(filename, outputBytes);
}
public static void Main()
{
byte[] fileBytes = File.ReadAllBytes("inputfile");
int filesOutput = 0;
int startIndex = -1;
int currentIndex = 0;
for (;;)
{
int nextIndex = Array.IndexOf(fileBytes, (byte)'G', currentIndex);
if (nextIndex == -1)
{
// There are no more ASCII 'G's in the file.
break;
}
if (nextIndex + 4 >= fileBytes.Length)
{
// There aren't enough characters left in the file for this
// to be an ASCII "GBIX" string.
break;
}
if (fileBytes[nextIndex+1] == (byte)'B' &&
fileBytes[nextIndex+2] == (byte)'I' &&
fileBytes[nextIndex+3] == (byte)'X')
{
// Found ASCII "GBIX" at nextIndex. Output the previous
// complete file, if there is one.
if (startIndex != -1)
{
Write(filesOutput, fileBytes, startIndex, nextIndex - startIndex);
}
filesOutput += 1;
startIndex = nextIndex;
}
currentIndex = nextIndex + 1;
}
if (startIndex != -1)
{
WriteFile(filesOutput, fileBytes, startIndex, fileBytes.Length - startIndex);
}
}
}