Reader for UCS-2 and UCS-4 encodings. (i.e., encodings from ISO-10646-UCS-(2|4)).
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.InputStream;
import java.io.IOException;
import java.io.Reader;
/**
* Reader for UCS-2 and UCS-4 encodings.
* (i.e., encodings from ISO-10646-UCS-(2|4)).
*
* @author Neil Graham, IBM
*
* @version $Id: UCSReader.java 515 2008-03-17 21:02:23Z jfrederic.clere@jboss.com $
*/
public class UCSReader extends Reader {
//
// Constants
//
/** Default byte buffer size (8192, larger than that of ASCIIReader
* since it's reasonable to surmise that the average UCS-4-encoded
* file should be 4 times as large as the average ASCII-encoded file).
*/
public static final int DEFAULT_BUFFER_SIZE = 8192;
public static final short UCS2LE = 1;
public static final short UCS2BE = 2;
public static final short UCS4LE = 4;
public static final short UCS4BE = 8;
//
// Data
//
/** Input stream. */
protected InputStream fInputStream;
/** Byte buffer. */
protected byte[] fBuffer;
// what kind of data we're dealing with
protected short fEncoding;
//
// Constructors
//
/**
* Constructs an ASCII reader from the specified input stream
* using the default buffer size. The Endian-ness and whether this is
* UCS-2 or UCS-4 needs also to be known in advance.
*
* @param inputStream The input stream.
* @param encoding One of UCS2LE, UCS2BE, UCS4LE or UCS4BE.
*/
public UCSReader(InputStream inputStream, short encoding) {
this(inputStream, DEFAULT_BUFFER_SIZE, encoding);
} // <init>(InputStream, short)
/**
* Constructs an ASCII reader from the specified input stream
* and buffer size. The Endian-ness and whether this is
* UCS-2 or UCS-4 needs also to be known in advance.
*
* @param inputStream The input stream.
* @param size The initial buffer size.
* @param encoding One of UCS2LE, UCS2BE, UCS4LE or UCS4BE.
*/
public UCSReader(InputStream inputStream, int size, short encoding) {
fInputStream = inputStream;
fBuffer = new byte[size];
fEncoding = encoding;
} // <init>(InputStream,int,short)
//
// Reader methods
//
/**
* Read a single character. This method will block until a character is
* available, an I/O error occurs, or the end of the stream is reached.
*
* <p> Subclasses that intend to support efficient single-character input
* should override this method.
*
* @return The character read, as an integer in the range 0 to 127
* (<tt>0x00-0x7f</tt>), or -1 if the end of the stream has
* been reached
*
* @exception IOException If an I/O error occurs
*/
public int read() throws IOException {
int b0 = fInputStream.read() & 0xff;
if (b0 == 0xff)
return -1;
int b1 = fInputStream.read() & 0xff;
if (b1 == 0xff)
return -1;
if(fEncoding >=4) {
int b2 = fInputStream.read() & 0xff;
if (b2 == 0xff)
return -1;
int b3 = fInputStream.read() & 0xff;
if (b3 == 0xff)
return -1;
if (fEncoding == UCS4BE)
return (b0<<24)+(b1<<16)+(b2<<8)+b3;
else
return (b3<<24)+(b2<<16)+(b1<<8)+b0;
} else { // UCS-2
if (fEncoding == UCS2BE)
return (b0<<8)+b1;
else
return (b1<<8)+b0;
}
} // read():int
/**
* Read characters into a portion of an array. This method will block
* until some input is available, an I/O error occurs, or the end of the
* stream is reached.
*
* @param ch Destination buffer
* @param offset Offset at which to start storing characters
* @param length Maximum number of characters to read
*
* @return The number of characters read, or -1 if the end of the
* stream has been reached
*
* @exception IOException If an I/O error occurs
*/
public int read(char ch[], int offset, int length) throws IOException {
int byteLength = length << ((fEncoding >= 4)?2:1);
if (byteLength > fBuffer.length) {
byteLength = fBuffer.length;
}
int count = fInputStream.read(fBuffer, 0, byteLength);
if(count == -1) return -1;
// try and make count be a multiple of the number of bytes we're looking for
if(fEncoding >= 4) { // BigEndian
// this looks ugly, but it avoids an if at any rate...
int numToRead = (4 - (count & 3) & 3);
for(int i=0; i<numToRead; i++) {
int charRead = fInputStream.read();
if(charRead == -1) { // end of input; something likely went wrong!A Pad buffer with nulls.
for (int j = i;j<numToRead; j++)
fBuffer[count+j] = 0;
break;
} else {
fBuffer[count+i] = (byte)charRead;
}
}
count += numToRead;
} else {
int numToRead = count & 1;
if(numToRead != 0) {
count++;
int charRead = fInputStream.read();
if(charRead == -1) { // end of input; something likely went wrong!A Pad buffer with nulls.
fBuffer[count] = 0;
} else {
fBuffer[count] = (byte)charRead;
}
}
}
// now count is a multiple of the right number of bytes
int numChars = count >> ((fEncoding >= 4)?2:1);
int curPos = 0;
for (int i = 0; i < numChars; i++) {
int b0 = fBuffer[curPos++] & 0xff;
int b1 = fBuffer[curPos++] & 0xff;
if(fEncoding >=4) {
int b2 = fBuffer[curPos++] & 0xff;
int b3 = fBuffer[curPos++] & 0xff;
if (fEncoding == UCS4BE)
ch[offset+i] = (char)((b0<<24)+(b1<<16)+(b2<<8)+b3);
else
ch[offset+i] = (char)((b3<<24)+(b2<<16)+(b1<<8)+b0);
} else { // UCS-2
if (fEncoding == UCS2BE)
ch[offset+i] = (char)((b0<<8)+b1);
else
ch[offset+i] = (char)((b1<<8)+b0);
}
}
return numChars;
} // read(char[],int,int)
/**
* Skip characters. This method will block until some characters are
* available, an I/O error occurs, or the end of the stream is reached.
*
* @param n The number of characters to skip
*
* @return The number of characters actually skipped
*
* @exception IOException If an I/O error occurs
*/
public long skip(long n) throws IOException {
// charWidth will represent the number of bits to move
// n leftward to get num of bytes to skip, and then move the result rightward
// to get num of chars effectively skipped.
// The trick with &'ing, as with elsewhere in this dcode, is
// intended to avoid an expensive use of / that might not be optimized
// away.
int charWidth = (fEncoding >=4)?2:1;
long bytesSkipped = fInputStream.skip(n<<charWidth);
if((bytesSkipped & (charWidth | 1)) == 0) return bytesSkipped >> charWidth;
return (bytesSkipped >> charWidth) + 1;
} // skip(long):long
/**
* Tell whether this stream is ready to be read.
*
* @return True if the next read() is guaranteed not to block for input,
* false otherwise. Note that returning false does not guarantee that the
* next read will block.
*
* @exception IOException If an I/O error occurs
*/
public boolean ready() throws IOException {
return false;
} // ready()
/**
* Tell whether this stream supports the mark() operation.
*/
public boolean markSupported() {
return fInputStream.markSupported();
} // markSupported()
/**
* Mark the present position in the stream. Subsequent calls to reset()
* will attempt to reposition the stream to this point. Not all
* character-input streams support the mark() operation.
*
* @param readAheadLimit Limit on the number of characters that may be
* read while still preserving the mark. After
* reading this many characters, attempting to
* reset the stream may fail.
*
* @exception IOException If the stream does not support mark(),
* or if some other I/O error occurs
*/
public void mark(int readAheadLimit) throws IOException {
fInputStream.mark(readAheadLimit);
} // mark(int)
/**
* Reset the stream. If the stream has been marked, then attempt to
* reposition it at the mark. If the stream has not been marked, then
* attempt to reset it in some way appropriate to the particular stream,
* for example by repositioning it to its starting point. Not all
* character-input streams support the reset() operation, and some support
* reset() without supporting mark().
*
* @exception IOException If the stream has not been marked,
* or if the mark has been invalidated,
* or if the stream does not support reset(),
* or if some other I/O error occurs
*/
public void reset() throws IOException {
fInputStream.reset();
} // reset()
/**
* Close the stream. Once a stream has been closed, further read(),
* ready(), mark(), or reset() invocations will throw an IOException.
* Closing a previously-closed stream, however, has no effect.
*
* @exception IOException If an I/O error occurs
*/
public void close() throws IOException {
fInputStream.close();
} // close()
} // class UCSReader
Related examples in the same category
1. | Convert Encoding | | |
2. | Utility class for working with character sets | | |
3. | Utility methods for ASCII character checking. | | |
4. | Conversions between IANA encoding names and Java encoding names, and vice versa. | | |
5. | ASCII character handling functions | | |
6. | This class represents an encoding. | | |
7. | Provides information about encodings. | | |
8. | Codec for the Quoted-Printable section of http://www.ietf.org/rfc/rfc1521.txt (RFC 1521) | | |
9. | ISO 8859-8, ASCII plus Hebrew | | |
10. | TIS-620 does not have the non-breaking space or the C1 controls. | | |
11. | ISO-8859-1; a.k.a. Latin-1 | | |
12. | ISO 8859-2, a.k.a. Latin-2 | | |
13. | ISO 8859-3 | | |
14. | ISO 8859-4, Latin plus the characters needed for Greenlandic, Icelandic, and Lappish. | | |
15. | ISO 8859-9 for Turkish. | | |
16. | ISO-8859-10, for Lithuanian, Estonian, Greenlandic, Icelandic, Inuit, Lappish, and other Northern European languages. | | |
17. | ISO-8859-13, for Latvian and other Baltic languages. | | |
18. | ISO-8859-14, for Gaelic, Welsh, and other Celtic languages. | | |
19. | ISO 8859-9 for Western Europe. Includes the Euro sign and several uncommon French letters | | |
20. | ISO 8859-16, Romanian | | |
21. | ASCII Writer | | |
22. | UCS Writer | | |
23. | Unicode Writer | | |
24. | Whether a character is or is not available in a particular encoding | | |
25. | ISO 8859-6, ASCII plus Arabic | | |
26. | ISO 8859-5, ASCII plus Cyrillic (Russian, Byelorussian, etc.) | | |
27. | ISO 8859-7, ASCII plus Greek | | |
28. | IANA to Java Mapping | | |
29. | Java to IANA Mapping | | |
30. | EncodingMap is a convenience class which handles conversions between IANA encoding names and Java encoding names, and vice versa. | | |
31. | Get file encoding | | |