算术编码压缩算法



我正在尝试实现算术编码,这是一种压缩算法。这是我编译时的压缩代码,它每次都显示"用法: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
    }
}

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

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

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

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

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:output5.txtyourInputFile.txt . 换句话说,它会认为5.txt是一个文件夹。 这就是当你将new File与两个参数一起使用时它认为你的意思。

消息说明了问题所在。您需要将 jar 文件运行为

java ArithmeticCompress InputFile OutputFile

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

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

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

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

您的Java程序,如下命令,其中输入文件名将是输入文件的绝对路径,输出文件名将是输出文件的绝对路径。

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

从您的问题来看,您似乎不了解 args 和文件类构造函数。

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

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)期望第一个参数是目录,第二个参数是文件名。注意:如果您不确定正在使用什么方法或构造函数,您应该阅读 Javadocs!在这里,您应该使用:

    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. 如果要对代码
  4. 中的文件路径进行硬编码,则应删除以下代码:

    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");
    

最新更新