java - 根据文件头数据确定文件扩展名的设计

标签 java arraylist nodes

我有一个问题,我已经想了两天了,但在网上(或这里)没有找到任何东西,所以我想我应该发布这个问题,看看我得到什么样的反馈。我一直在业余时间编写一个小程序,该程序扫描文件目录(已删除文件扩展名)并读取每个文件的文件头,以便找出每个文件的文件扩展名。到目前为止我已经使用了一系列的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/

相关文章:

java - 拆分器返回空数组列表 Spring 集成

JavaScript:将节点复制到 DocumentFragment

c - 插入AVL树的函数不会插入

java - 在 Java 9 中如何针对 jar 文件进行编译?

java - 如何从ArrayList中删除Sprite/Object?

java - 保留先前变量和输出的信息

java - 将多个 "randomly generated"对象添加到 ArrayList 导致多次添加同一个对象

javascript - Mithril 模板转换器使用

java - 无法从另一个java程序运行一个java程序

java - Spring Boot Maven 插件 - 没有 BOOT-INF 目录