我有一个问题,我已经想了两天了,但在网上(或这里)没有找到任何东西,所以我想我应该发布这个问题,看看我得到什么样的反馈。我一直在业余时间编写一个小程序,该程序扫描文件目录(已删除文件扩展名)并读取每个文件的文件头,以便找出每个文件的文件扩展名。到目前为止我已经使用了一系列的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. 特定文件类型的 header 信息的 byte[],以及 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 语句或 switch 更糟糕...第二个问题是,一旦我用所有 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;
}
最佳答案
您使用的方法非常复杂,导致代码难以维护。如果您同意修改整个设计,我想提出如下替代方法:
创建一个名为的接口(interface) 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
数组(您在示例中创建了两个字节数组。一个用于从数组读取的前 512 个字节,另一个用于与此数组进行比较)
关于java - 根据文件头数据确定文件扩展名的设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30410172/