1 package SevenZip; 2 3 public class LzmaAlone 4 { 5 static public class CommandLine 6 { 7 public static final int kEncode = 0; 8 public static final int kDecode = 1; 9 public static final int kBenchmak = 2; 10 11 public int Command = -1; 12 public int NumBenchmarkPasses = 10; 13 14 public int DictionarySize = 1 << 23; 15 public boolean DictionarySizeIsDefined = false; 16 17 public int Lc = 3; 18 public int Lp = 0; 19 public int Pb = 2; 20 21 public int Fb = 128; 22 public boolean FbIsDefined = false; 23 24 public boolean Eos = false; 25 26 public int Algorithm = 2; 27 public int MatchFinder = 1; 28 29 public String InFile; 30 public String OutFile; 31 32 boolean ParseSwitch(String s) 33 { 34 if (s.startsWith("d")) 35 { 36 DictionarySize = 1 << Integer.parseInt(s.substring(1)); 37 DictionarySizeIsDefined = true; 38 } 39 else if (s.startsWith("fb")) 40 { 41 Fb = Integer.parseInt(s.substring(2)); 42 FbIsDefined = true; 43 } 44 else if (s.startsWith("a")) 45 Algorithm = Integer.parseInt(s.substring(1)); 46 else if (s.startsWith("lc")) 47 Lc = Integer.parseInt(s.substring(2)); 48 else if (s.startsWith("lp")) 49 Lp = Integer.parseInt(s.substring(2)); 50 else if (s.startsWith("pb")) 51 Pb = Integer.parseInt(s.substring(2)); 52 else if (s.startsWith("eos")) 53 Eos = true; 54 else if (s.startsWith("mf")) 55 { 56 String mfs = s.substring(2); 57 if (mfs.equals("bt2")) 58 MatchFinder = 0; 59 else if (mfs.equals("bt4")) 60 MatchFinder = 1; 61 else if (mfs.equals("bt4b")) 62 MatchFinder = 2; 63 else 64 return false; 65 } 66 else 67 return false; 68 return true; 69 } 70 71 public boolean Parse(String[] args) throws Exception 72 { 73 int pos = 0; 74 boolean switchMode = true; 75 for (int i = 0; i < args.length; i++) 76 { 77 String s = args[i]; 78 if (s.length() == 0) 79 return false; 80 if (switchMode) 81 { 82 if (s.compareTo("--") == 0) 83 { 84 switchMode = false; 85 continue; 86 } 87 if (s.charAt(0) == '-') 88 { 89 String sw = s.substring(1).toLowerCase(); 90 if (sw.length() == 0) 91 return false; 92 try 93 { 94 if (!ParseSwitch(sw)) 95 return false; 96 } 97 catch (NumberFormatException e) 98 { 99 return false; 100 } 101 continue; 102 } 103 } 104 if (pos == 0) 105 { 106 if (s.equalsIgnoreCase("e")) 107 Command = kEncode; 108 else if (s.equalsIgnoreCase("d")) 109 Command = kDecode; 110 else if (s.equalsIgnoreCase("b")) 111 Command = kBenchmak; 112 else 113 return false; 114 } 115 else if(pos == 1) 116 { 117 if (Command == kBenchmak) 118 { 119 try 120 { 121 NumBenchmarkPasses = Integer.parseInt(s); 122 if (NumBenchmarkPasses < 1) 123 return false; 124 } 125 catch (NumberFormatException e) 126 { 127 return false; 128 } 129 } 130 else 131 InFile = s; 132 } 133 else if(pos == 2) 134 OutFile = s; 135 else 136 return false; 137 pos++; 138 continue; 139 } 140 return true; 141 } 142 } 143 144 145 static void PrintHelp() 146 { 147 System.out.println( 148 "\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + 149 " e: encode file\n" + 150 " d: decode file\n" + 151 " b: Benchmark\n" + 152 "<Switches>\n" + 153 // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + 154 " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + 155 " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + 156 " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + 157 " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + 158 " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + 159 " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + 160 " -eos: write End Of Stream marker\n" 161 ); 162 } 163 164 public static void main(String[] args) throws Exception 165 { 166 System.out.println("\nLZMA (Java) 4.61 2008-11-23\n"); 167 168 if (args.length < 1) 169 { 170 PrintHelp(); 171 return; 172 } 173 174 CommandLine params = new CommandLine(); 175 if (!params.Parse(args)) 176 { 177 System.out.println("\nIncorrect command"); 178 return; 179 } 180 181 if (params.Command == CommandLine.kBenchmak) 182 { 183 int dictionary = (1 << 21); 184 if (params.DictionarySizeIsDefined) 185 dictionary = params.DictionarySize; 186 if (params.MatchFinder > 1) 187 throw new Exception("Unsupported match finder"); 188 SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary); 189 } 190 else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode) 191 { 192 java.io.File inFile = new java.io.File(params.InFile); 193 java.io.File outFile = new java.io.File(params.OutFile); 194 195 java.io.BufferedInputStream inStream = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile)); 196 java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile)); 197 198 boolean eos = false; 199 if (params.Eos) 200 eos = true; 201 if (params.Command == CommandLine.kEncode) 202 { 203 SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); 204 if (!encoder.SetAlgorithm(params.Algorithm)) 205 throw new Exception("Incorrect compression mode"); 206 if (!encoder.SetDictionarySize(params.DictionarySize)) 207 throw new Exception("Incorrect dictionary size"); 208 if (!encoder.SetNumFastBytes(params.Fb)) 209 throw new Exception("Incorrect -fb value"); 210 if (!encoder.SetMatchFinder(params.MatchFinder)) 211 throw new Exception("Incorrect -mf value"); 212 if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb)) 213 throw new Exception("Incorrect -lc or -lp or -pb value"); 214 encoder.SetEndMarkerMode(eos); 215 encoder.WriteCoderProperties(outStream); 216 long fileSize; 217 if (eos) 218 fileSize = -1; 219 else 220 fileSize = inFile.length(); 221 for (int i = 0; i < 8; i++) 222 outStream.write((int)(fileSize >>> (8 * i)) & 0xFF); 223 encoder.Code(inStream, outStream, -1, -1, null); 224 } 225 else 226 { 227 int propertiesSize = 5; 228 byte[] properties = new byte[propertiesSize]; 229 if (inStream.read(properties, 0, propertiesSize) != propertiesSize) 230 throw new Exception("input .lzma file is too short"); 231 SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); 232 if (!decoder.SetDecoderProperties(properties)) 233 throw new Exception("Incorrect stream properties"); 234 long outSize = 0; 235 for (int i = 0; i < 8; i++) 236 { 237 int v = inStream.read(); 238 if (v < 0) 239 throw new Exception("Can't read stream size"); 240 outSize |= ((long)v) << (8 * i); 241 } 242 if (!decoder.Code(inStream, outStream, outSize)) 243 throw new Exception("Error in data stream"); 244 } 245 outStream.flush(); 246 outStream.close(); 247 inStream.close(); 248 } 249 else 250 throw new Exception("Incorrect command"); 251 return; 252 } 253 } 254