1:
42: package ;
43:
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59:
60:
70: public class Base64 {
71:
72: private Base64 ()
73: {
74: }
75:
76:
83: public static char[] encode(final byte[] data) {
84: final char[] out = new char[((data.length + 2) / 3) * 4];
85:
86:
87:
88:
89:
90: for (int i = 0, index = 0; i < data.length; i += 3, index += 4) {
91: boolean quad = false;
92: boolean trip = false;
93:
94: int val = (0xFF & data[i]);
95: val <<= 8;
96: if ((i + 1) < data.length) {
97: val |= (0xFF & data[i + 1]);
98: trip = true;
99: }
100: val <<= 8;
101: if ((i + 2) < data.length) {
102: val |= (0xFF & data[i + 2]);
103: quad = true;
104: }
105: out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)];
106: val >>= 6;
107: out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)];
108: val >>= 6;
109: out[index + 1] = alphabet[val & 0x3F];
110: val >>= 6;
111: out[index + 0] = alphabet[val & 0x3F];
112: }
113: return out;
114: }
115:
116:
131: public static byte[] decode(final char[] data) {
132:
133:
134:
135:
136:
137:
138:
139: int tempLen = data.length;
140: for (int ix = 0; ix < data.length; ix++) {
141: if ((data[ix] > 255) || codes[data[ix]] < 0) {
142: --tempLen;
143: }
144: }
145:
146:
147:
148:
149:
150: int len = (tempLen / 4) * 3;
151: if ((tempLen % 4) == 3) {
152: len += 2;
153: }
154: if ((tempLen % 4) == 2) {
155: len += 1;
156: }
157:
158: final byte[] out = new byte[len];
159:
160:
161: int shift = 0;
162: int accum = 0;
163: int index = 0;
164:
165:
166: for (int ix = 0; ix < data.length; ix++) {
167: final int value = (data[ix] > 255) ? -1 : codes[data[ix]];
168:
169: if (value >= 0) {
170: accum <<= 6;
171: shift += 6;
172: accum |= value;
173: if (shift >= 8) {
174: shift -= 8;
175: out[index++] =
176: (byte) ((accum >> shift) & 0xff);
177: }
178: }
179:
180:
181:
182:
183:
184:
185: }
186:
187:
188: if (index != out.length) {
189: throw new Error("Miscalculated data length (wrote "
190: + index + " instead of " + out.length + ")");
191: }
192:
193: return out;
194: }
195:
196:
197:
198:
199:
200: private static char[] alphabet =
201: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharArray();
202:
203:
204:
205:
206: private static byte[] codes = new byte[256];
207:
208: static {
209: for (int i = 0; i < 256; i++) {
210: codes[i] = -1;
211: }
212: for (int i = 'A'; i <= 'Z'; i++) {
213: codes[i] = (byte) (i - 'A');
214: }
215: for (int i = 'a'; i <= 'z'; i++) {
216: codes[i] = (byte) (26 + i - 'a');
217: }
218: for (int i = '0'; i <= '9'; i++) {
219: codes[i] = (byte) (52 + i - '0');
220: }
221: codes['+'] = 62;
222: codes['/'] = 63;
223: }
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
238: public static void main(final String[] args) {
239: boolean decode = false;
240:
241: if (args.length == 0) {
242: System.out.println("usage: java Base64 [-d[ecode]] filename");
243: System.exit(0);
244: }
245: for (int i = 0; i < args.length; i++) {
246: if ("-decode".equalsIgnoreCase(args[i])) {
247: decode = true;
248: }
249: else if ("-d".equalsIgnoreCase(args[i])) {
250: decode = true;
251: }
252: }
253:
254: final String filename = args[args.length - 1];
255: final File file = new File(filename);
256: if (!file.exists()) {
257: System.out.println("Error: file '" + filename + "' doesn't exist!");
258: System.exit(0);
259: }
260:
261: if (decode) {
262: final char[] encoded = readChars(file);
263: final byte[] decoded = decode(encoded);
264: writeBytes(file, decoded);
265: }
266: else {
267: final byte[] decoded = readBytes(file);
268: final char[] encoded = encode(decoded);
269: writeChars(file, encoded);
270: }
271: }
272:
273: private static byte[] readBytes(final File file) {
274: final ByteArrayOutputStream baos = new ByteArrayOutputStream();
275: try {
276: final InputStream fis = new FileInputStream(file);
277: final InputStream is = new BufferedInputStream(fis);
278:
279: int count;
280: final byte[] buf = new byte[16384];
281: while ((count = is.read(buf)) != -1) {
282: if (count > 0) {
283: baos.write(buf, 0, count);
284: }
285: }
286: is.close();
287: }
288: catch (Exception e) {
289: e.printStackTrace();
290: }
291:
292: return baos.toByteArray();
293: }
294:
295: private static char[] readChars(final File file) {
296: final CharArrayWriter caw = new CharArrayWriter();
297: try {
298: final Reader fr = new FileReader(file);
299: final Reader in = new BufferedReader(fr);
300: int count;
301: final char[] buf = new char[16384];
302: while ((count = in.read(buf)) != -1) {
303: if (count > 0) {
304: caw.write(buf, 0, count);
305: }
306: }
307: in.close();
308: }
309: catch (Exception e) {
310: e.printStackTrace();
311: }
312:
313: return caw.toCharArray();
314: }
315:
316: private static void writeBytes(final File file, final byte[] data) {
317: try {
318: final OutputStream fos = new FileOutputStream(file);
319: final OutputStream os = new BufferedOutputStream(fos);
320: os.write(data);
321: os.close();
322: }
323: catch (Exception e) {
324: e.printStackTrace();
325: }
326: }
327:
328: private static void writeChars(final File file, final char[] data) {
329: try {
330: final Writer fos = new FileWriter(file);
331: final Writer os = new BufferedWriter(fos);
332: os.write(data);
333: os.close();
334: }
335: catch (Exception e) {
336: e.printStackTrace();
337: }
338: }
339:
340:
341:
342:
343: }