我有一个问题,我一直试图将我的头脑包裹两天,并且没有在网上找到任何东西(或在这里),所以我想我会发布这个问题,看看我有什么样的反馈意见得到。我在业余时间编写了一个小程序,它扫描文件目录(删除了文件扩展名)并读取每个文件的文件头,以便找出每个文件的文件扩展名。到目前为止,我已经使用了一系列if / else if语句来满足"模式匹配"我的计划的功能......
private String fileHeaderCheck()
{
/* ----- PNG File Type Verification ----- */
if (headerCheck.buffer[0] == 0x89 && headerCheck.buffer[1] == 0x50 && headerCheck.buffer[2] == 0x4E && headerCheck.buffer[3] == 0x47
&& headerCheck.buffer[4] == 0xD && headerCheck.buffer[5] == 0xA && headerCheck.buffer[6] == 0x1A && headerCheck.buffer[7] == 0xA)
{
return ".png";
}
/* ----- JPG File Type Verification ----- */
else if (headerCheck.buffer[0] == 0xFF && headerCheck.buffer[1] == 0xD8 && headerCheck.buffer[2] == 0xFF && headerCheck.buffer[3] == 0xE0)
{
return ".jpg";
}
// And so on and so on through the whole list of file types I am checking for
else
return "unknown";
}
headerCheck是一个Buffer对象,它包含一个byte [],用于保存从文件的前512个字节读入的数据。我在这个模式匹配过程中加入了25-30种不同的文件类型,因此您可以看到该函数将很快变得庞大和丑陋。我想要做的是使用Node对象的ArrayList,每个对象包含:1。特定文件类型的标题信息的字节[],以及2.表示文件扩展类型的字符串, 然后只是遍历数组,比较Node byte []和headerCheck.buffer [],无论匹配什么元素,我都会将它的fileType附加到我在headerCheck.buffer []中读取的文件的末尾。从。我的Node类以这种方式设置....
class Node //if this is the "png" Node
{
byte[] metadata;
String fileType;
Node()
{
this.metadata = new byte[]{0x89, 0x50, 0x4E, 0x47, 0xD, 0xA, 0x1A, 0xA};
this.fileType = ".png";
}
}
我无法弄清楚如何初始化ArrayList。我是否必须使用预配置的数据创建/实例化25-30个单独的节点类,以初始化ArrayList,然后将()添加到它?这似乎比所有if / else if语句或开关更糟糕......第二个问题是,一旦我使用所有Node对象实例化我的ArrayList,我就无法直观地看到如何迭代它的byte []为了将它与headerCheck.buffer []进行比较。我正在推动我的知识界限所以对于这些问题,我没有代码,因为我不知道从哪里开始编码这些东西。我正在考虑使用双嵌套for循环,但我还没有达到那么远,因为我还没有找到一种初始化ArrayList的有效方法。我甚至考虑过一些设计模式作为可能的补救措施,但无济于事。任何帮助将不胜感激...谢谢
迭代方法(沿着这些方向):
boolean match;
for (int x = 0; x < pattens.get(metadata).size(); x++)
{
if (headerCheck.buffer[x] != patterns.get(metadata[x])
{
match = false;
return;
}
else
return true;
}
答案 0 :(得分:1)
您使用的是一种非常复杂的方法,导致代码难以维护。如果你可以改进整个设计,我想提出一个如下的替代方法:
创建名为 FileExtension
的接口:
interface FileExtension {
public String getExtension(byte[] buffer);
}
创建包含用于确定文件扩展名的逻辑的类:
class PNGExtension implements FileExtension {
@Override
public String getExtension(byte[] buffer) {
/* ----- PNG File Type Verification ----- */
String fileType = null;
if (buffer[0] == 0x89 && buffer[1] == 0x50 && buffer[2] == 0x4E && buffer[3] == 0x47 && buffer[4] == 0xD && buffer[5] == 0xA
&& buffer[6] == 0x1A && buffer[7] == 0xA) {
fileType = ".png";
}
return fileType;
}
}
class JPGExtension implements FileExtension {
@Override
public String getExtension(byte[] buffer) {
/* ----- JPG File Type Verification ----- */
String fileType = null;
if (buffer[0] == 0xFF && buffer[1] == 0xD8 && buffer[2] == 0xFF && buffer[3] == 0xE0) {
fileType = ".jpg";
}
return fileType;
}
}
创建一个最终将用于根据前512个字节获取文件扩展名的复合具体类:
class CompositeFileExtension implements FileExtension {
private List<FileExtension> fileExtensions;
public CompositeFileExtension() {
//in the real world, this list can be populated through an IoC container
fileExtensions = new ArrayList<FileExtension>();
fileExtensions.add(new PNGExtension());
fileExtensions.add(new JPGExtension());
}
@Override
public String getExtension(byte[] buffer) {
String fileExtension = null;
for(FileExtension extension : fileExtensions) {
if((fileExtension=extension.getExtension(buffer))!=null) {
break;
}
}
return fileExtension;
}
}
最后,放在一起的所有代码片段将按如下方式工作:
public class FileMapperDemo {
public static void main(String[] args) {
/*
* 1. For each file in directory
* 2. Read first 512 bytes into buffer array
* 3. Create a new CompositeFileExtension object and pass it the buffer
*
*/
CompositeFileExtension fileExtensions = new CompositeFileExtension();
//4. get the file extension
String fileExtension = fileExtensions.getExtension(buffer);
}
}
这种方法的优点是,只要需要从缓冲区推导出新类型的文件扩展名,您只需要向FileExtension
添加新的ArrayList
个对象。您不需要创建两个类似的byte
数组(您可以在example.One中创建两个字节数组,用于从数组中读取的前512个字节,另一个用于与此数组进行比较)
答案 1 :(得分:0)
您可以将节点类更改为以下内容:
class FilePattern {
byte[] metadata ;
String extension ;
public FilePattern(byte[] m, String ext) {
this.metadata = m ;
this.extension = ext ;
}
/* add the getters here */
}
现在,您可以在向其添加元素时初始化ArrayList,即
ArrayList<FilePattern> patterns = new ArrayList<FilePattern>();
patterns.add(new FilePattern(new byte[]{ ... }, "extension"));
.... // for other patterns.
接下来,循环遍历patterns
的元素,提取元数据字节并与从文件读取的字节匹配并确定文件类型。
修改:对于循环,您可以执行以下操作:
for(FilePattern f : patterns)
if(Arrays.equals(f.getMetadata(), headerCheck.buffer))
System.out.println("Found file with extension : ", f.getExtension());