算术编码压缩算法

时间:2015-01-12 18:42:59

标签: java algorithm

我正在尝试实现算术编码,这是一种压缩算法。这是压缩代码,当我编译它时,它显示"用法:java ArithmeticCompress InputFile OutputFile"每次。我已经提供了文件路径,但不了解问题是什么?

public class ArithmeticCompress {

    public static void main(String[] args) throws IOException {
        // Show what command line arguments to use
        if (args.length == 0) {
            System.err.println("Usage: java ArithmeticCompress InputFile OutputFile");
            System.exit(1);
            return;
        }

        // Otherwise, compress

        File inputFile = new File("E:\\output\\5.txt", args[0]);
        File outputFile = new File("E:\\output\\new.txt", args[1]);

        // Read input file once to compute symbol frequencies
        FrequencyTable freq = getFrequencies(inputFile);
        freq.increment(256);  // EOF symbol gets a frequency of 1

        // Read input file again, compress with arithmetic coding, and write output file
        InputStream in = new BufferedInputStream(new FileInputStream(inputFile));
        BitOutputStream out = new BitOutputStream(new BufferedOutputStream(new FileOutputStream(outputFile)));
        try {
            writeFrequencies(out, freq);
            compress(freq, in, out);
        } finally {
            out.close();
            in.close();
        }
    }


    private static FrequencyTable getFrequencies(File file) throws IOException {
        FrequencyTable freq = new SimpleFrequencyTable(new int[257]);
        InputStream input = new BufferedInputStream(new FileInputStream(file));
        try {
            while (true) {
                int b = input.read();
                if (b == -1)
                    break;
                freq.increment(b);
            }
        } finally {
            input.close();
        }
        return freq;
    }


    static void writeFrequencies(BitOutputStream out, FrequencyTable freq) throws IOException {
        for (int i = 0; i < 256; i++)
            writeInt(out, 32, freq.get(i));
    }


    static void compress(FrequencyTable freq, InputStream in, BitOutputStream out) throws IOException {
        ArithmeticEncoder enc = new ArithmeticEncoder(out);
        while (true) {
            int b = in.read();
            if (b == -1)
                break;
            enc.write(freq, b);
        }
        enc.write(freq, 256);  // EOF
        enc.finish();
    }


    private static void writeInt(BitOutputStream out, int numbits, int value) throws IOException {
        if (numbits < 0 || numbits > 32)
            throw new IllegalArgumentException();

        for (int i = 0; i < numbits; i++)
            out.write(value >>> i & 1);  // Little endian
    }

}

4 个答案:

答案 0 :(得分:3)

你说你已经给出了文件路径。但是,您尝试将文件路径放在程序本身中,而不是命令行中:

File inputFile = new File("E:\\output\\5.txt", args[0]);

这还不够好。如果程序希望文件路径位于命令行上,则必须在运行时将其放在命令行上(请参阅其他答案)。 Java不会查看您的程序,并确定您的程序中确实有路径名。电脑根本就不聪明。

您需要做出决定。如果您希望文件路径在程序中,那么请删除检查args.length的代码,并且不要在args构造函数中使用new File

File inputFile = new File("E:\\output\\5.txt");
File outputFile = new File("E:\\output\\new.txt");

如果要在命令行中指定文件,请将代码更改为:

File inputFile = new File(args[0]);
File outputFile = new File(args[1]);

并确保在使用java运行程序时指定路径名。

这不起作用:

File inputFile = new File("E:\\output\\5.txt", args[0]);

因为现在它会查找名为E:\output\5.txt\yourInputFile.txt的文件。换句话说,它会认为5.txt是一个文件夹。当你使用带有两个参数的new File时,这就是它的意思。

答案 1 :(得分:1)

该消息说明了什么错。您需要以

运行jar文件
java ArithmeticCompress InputFile OutputFile

因此,如果您将带有ArithmicCompress的jar文件命名为ArithmicCompress作为主类,则使用输入文件和输出文件参数运行它应跳过该部分并尝试运行它。

基本上,它现在说你没有提供参数,所以要么另一个类作为主类运行,要么你不提供参数。

如果您确定要提供参数,请在正在运行的任何类中使用以下代码段验证它,它应该返回您提供的参数;

for (int i = 0; i < args.length; i++) {
    System.out.println(args[i]);
}

答案 2 :(得分:1)

运行你的java程序如下命令,其中输入文件名将是输入文件的绝对路径,输出文件名将是输出文件的绝对路径。

java <class-name> "<input file name>" "<output file name>"

答案 3 :(得分:1)

从你的问题来看,你似乎没有理解args和File Class构造函数。

让我在这里解释一下代码,以帮助您理解问题:

public static void main(String[] args) throws IOException {
    // Show what command line arguments to use
    if (args.length == 0) {
        System.err.println("Usage: java ArithmeticCompress InputFile OutputFile");
        System.exit(1);
        return;
    }

   ..some code...

    File inputFile = new File("E:\\output\\5.txt", args[0]);
    File outputFile = new File("E:\\output\\new.txt", args[1]);

   ..some code...
}

  1. 此处main(String[] args)表示从命令行运行此程序时,您可以提供多个String参数,如下所示:java ClassName argument1 argument2 ...

    这些参数可以在主函数中分别以args [0],args [1],args [2]的形式访问。 因为String[] args是一个字符串数组。

    因此,如果您看到比较if (args.length == 0)会显示错误消息

    Usage: java ArithmeticCompress InputFile OutputFile
    

    如果String[] args的长度等于零,那么您需要提供一些参数。

  2. 调用new File("E:\\output\\5.txt", args[0]);构造函数是错误的,因为File(String, String)期望第一个参数是目录,第二个参数是filename。注意:如果您不确定使用的是哪种方法或构造函数,则应阅读Javadoc! 在这里你应该使用:

    File inputFile = new File("E:\\output", args[0]);
    File outputFile = new File("E:\\output", args[1]);
    

    并提供两个仅包含文件名的参数,或者您应该尝试:

    File inputFile = new File(args[0]);
    File outputFile = new File(args[1]);
    

    并提供两个带完整文件路径的参数。

  3. 如果您想对代码中的文件路径进行硬编码,请删除以下代码:

    if (args.length == 0) {
        System.err.println("Usage: java ArithmeticCompress InputFile OutputFile");
        System.exit(1);
        return;
    }
    

    并在File构造函数中对路径进行硬编码,如下所示:

    File inputFile = new File("E:\\output\\5.txt");
    File outputFile = new File("E:\\output\\new.txt");