KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > knowgate > misc > Base64Encoder


1 // Copyright (C) 1999-2002 by Jason Hunter <jhunter_AT_acm_DOT_org>.
2
// All rights reserved. Use of this class is limited.
3
// Please see the LICENSE for more information.
4

5 package com.knowgate.misc;
6
7 import java.io.*;
8
9 /**
10  * <p>A class to encode Base64 streams and strings.</p>
11  * <p>See RFC 1521 section 5.2 for details of the Base64 algorithm.</p>
12  * <p>
13  * This class can be used for encoding strings:
14  * <blockquote><pre>
15  * String unencoded = "webmaster:try2gueSS";
16  * String encoded = Base64Encoder.encode(unencoded);
17  * </pre></blockquote>
18  * or for encoding streams:
19  * <blockquote><pre>
20  * OutputStream out = new Base64Encoder(System.out);
21  * </pre></blockquote>
22  *
23  * @author <b>Jason Hunter</b>, Copyright &#169; 2000
24  * @version 1.2, 2002/11/01, added encode(byte[]) method to better handle
25  * binary data (thanks to Sean Graham)
26  * @version 1.1, 2000/11/17, fixed bug with sign bit for char values
27  * @version 1.0, 2000/06/11
28  */

29 public class Base64Encoder extends FilterOutputStream {
30
31   private static final char[] chars = {
32     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
33     'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
34     'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
35     'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
36     'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
37     'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
38     '8', '9', '+', '/'
39   };
40
41   private int charCount;
42   private int carryOver;
43
44   /**
45    * Constructs a new Base64 encoder that writes output to the given
46    * OutputStream.
47    *
48    * @param out the output stream
49    */

50   public Base64Encoder(OutputStream out) {
51     super(out);
52   }
53
54   /**
55    * Writes the given byte to the output stream in an encoded form.
56    *
57    * @exception IOException if an I/O error occurs
58    */

59   public void write(int b) throws IOException {
60     // Take 24-bits from three octets, translate into four encoded chars
61
// Break lines at 76 chars
62
// If necessary, pad with 0 bits on the right at the end
63
// Use = signs as padding at the end to ensure encodedLength % 4 == 0
64

65     // Remove the sign bit,
66
// thanks to Christian Schweingruber <chrigu@lorraine.ch>
67
if (b < 0) {
68       b += 256;
69     }
70
71     // First byte use first six bits, save last two bits
72
if (charCount % 3 == 0) {
73       int lookup = b >> 2;
74       carryOver = b & 3; // last two bits
75
out.write(chars[lookup]);
76     }
77     // Second byte use previous two bits and first four new bits,
78
// save last four bits
79
else if (charCount % 3 == 1) {
80       int lookup = ((carryOver << 4) + (b >> 4)) & 63;
81       carryOver = b & 15; // last four bits
82
out.write(chars[lookup]);
83     }
84     // Third byte use previous four bits and first two new bits,
85
// then use last six new bits
86
else if (charCount % 3 == 2) {
87       int lookup = ((carryOver << 2) + (b >> 6)) & 63;
88       out.write(chars[lookup]);
89       lookup = b & 63; // last six bits
90
out.write(chars[lookup]);
91       carryOver = 0;
92     }
93     charCount++;
94
95     // Add newline every 76 output chars (that's 57 input chars)
96
if (charCount % 57 == 0) {
97       out.write('\n');
98     }
99   }
100
101   /**
102    * Writes the given byte array to the output stream in an
103    * encoded form.
104    *
105    * @param b the data to be written
106    * @param off the start offset of the data
107    * @param len the length of the data
108    * @exception IOException if an I/O error occurs
109    */

110   public void write(byte[] buf, int off, int len) throws IOException {
111     // This could of course be optimized
112
for (int i = 0; i < len; i++) {
113       write(buf[off + i]);
114     }
115   }
116
117   /**
118    * Closes the stream, this MUST be called to ensure proper padding is
119    * written to the end of the output stream.
120    *
121    * @exception IOException if an I/O error occurs
122    */

123   public void close() throws IOException {
124     // Handle leftover bytes
125
if (charCount % 3 == 1) { // one leftover
126
int lookup = (carryOver << 4) & 63;
127       out.write(chars[lookup]);
128       out.write('=');
129       out.write('=');
130     }
131     else if (charCount % 3 == 2) { // two leftovers
132
int lookup = (carryOver << 2) & 63;
133       out.write(chars[lookup]);
134       out.write('=');
135     }
136     super.close();
137   }
138
139   /**
140    * Returns the encoded form of the given unencoded string. The encoder
141    * uses the ISO-8859-1 (Latin-1) encoding to convert the string to bytes.
142    * For greater control over the encoding, encode the string to bytes
143    * yourself and use encode(byte[]).
144    *
145    * @param unencoded the string to encode
146    * @return the encoded form of the unencoded string
147    */

148   public static String JavaDoc encode(String JavaDoc unencoded) {
149     byte[] bytes = null;
150     try {
151       bytes = unencoded.getBytes("8859_1");
152     }
153     catch (UnsupportedEncodingException ignored) { }
154     return encode(bytes);
155   }
156
157   /**
158    * Returns the encoded form of the given unencoded string.
159    *
160    * @param unencoded the string to encode
161    * @return the encoded form of the unencoded string
162    */

163   public static String JavaDoc encode(byte[] bytes) {
164     ByteArrayOutputStream out =
165       new ByteArrayOutputStream((int) (bytes.length * 1.37));
166     Base64Encoder encodedOut = new Base64Encoder(out);
167
168     try {
169       encodedOut.write(bytes);
170       encodedOut.close();
171
172       return out.toString("8859_1");
173     }
174     catch (IOException ignored) { return null; }
175   }
176
177   public static void main(String JavaDoc[] args) throws Exception JavaDoc {
178     if (args.length != 1) {
179       System.err.println(
180         "Usage: java com.oreilly.servlet.Base64Encoder fileToEncode");
181       return;
182     }
183
184     Base64Encoder encoder = null;
185     BufferedInputStream in = null;
186     try {
187       encoder = new Base64Encoder(System.out);
188       in = new BufferedInputStream(new FileInputStream(args[0]));
189
190       byte[] buf = new byte[4 * 1024]; // 4K buffer
191
int bytesRead;
192       while ((bytesRead = in.read(buf)) != -1) {
193         encoder.write(buf, 0, bytesRead);
194       }
195     }
196     finally {
197       if (in != null) in.close();
198       if (encoder != null) encoder.close();
199     }
200   }
201 }
202
Popular Tags