2 *******************************************************************************
3 * Copyright (C) 2001-2011, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
8 package com.ibm.icu.impl.data;
10 import java.io.BufferedReader;
11 import java.io.IOException;
12 import java.io.InputStream;
13 import java.io.InputStreamReader;
14 import java.io.UnsupportedEncodingException;
16 import com.ibm.icu.impl.ICUData;
17 import com.ibm.icu.impl.PatternProps;
20 * A reader for text resource data in the current package or the package
21 * of a given class object. The
22 * resource data is loaded through the class loader, so it will
23 * typically be a file in the same directory as the *.class files, or
24 * a file within a JAR file in the corresponding subdirectory. The
25 * file must be a text file in one of the supported encodings; when the
26 * resource is opened by constructing a <code>ResourceReader</code>
27 * object the encoding is specified.
31 public class ResourceReader {
32 private BufferedReader reader;
33 private String resourceName;
34 private String encoding; // null for default encoding
35 private Class<?> root;
38 * The one-based line number. Has the special value -1 before the
39 * object is initialized. Has the special value 0 after initialization
40 * but before the first line is read.
45 * Construct a reader object for the text file of the given name
46 * in this package, using the given encoding.
47 * @param resourceName the name of the text file located in this
48 * package's ".data" subpackage.
49 * @param encoding the encoding of the text file; if unsupported
50 * an exception is thrown
51 * @exception UnsupportedEncodingException if
52 * <code>encoding</code> is not supported by the JDK.
54 public ResourceReader(String resourceName, String encoding)
55 throws UnsupportedEncodingException {
56 this(ICUData.class, "data/" + resourceName, encoding);
60 * Construct a reader object for the text file of the given name
61 * in this package, using the default encoding.
62 * @param resourceName the name of the text file located in this
63 * package's ".data" subpackage.
65 public ResourceReader(String resourceName) {
66 this(ICUData.class, "data/" + resourceName);
70 * Construct a reader object for the text file of the given name
71 * in the given class's package, using the given encoding.
72 * @param resourceName the name of the text file located in the
73 * given class's package.
74 * @param encoding the encoding of the text file; if unsupported
75 * an exception is thrown
76 * @exception UnsupportedEncodingException if
77 * <code>encoding</code> is not supported by the JDK.
79 public ResourceReader(Class<?> rootClass, String resourceName, String encoding)
80 throws UnsupportedEncodingException {
81 this.root = rootClass;
82 this.resourceName = resourceName;
83 this.encoding = encoding;
89 * Construct a reader object for the input stream associated with
90 * the given resource name.
91 * @param is the input stream of the resource
92 * @param resourceName the name of the resource
94 public ResourceReader(InputStream is, String resourceName, String encoding) {
96 this.resourceName = resourceName;
97 this.encoding = encoding;
101 InputStreamReader isr = (encoding == null)
102 ? new InputStreamReader(is)
103 : new InputStreamReader(is, encoding);
105 this.reader = new BufferedReader(isr);
108 catch (UnsupportedEncodingException e) {
113 * Construct a reader object for the input stream associated with
114 * the given resource name.
115 * @param is the input stream of the resource
116 * @param resourceName the name of the resource
118 public ResourceReader(InputStream is, String resourceName) {
119 this(is, resourceName, null);
123 * Construct a reader object for the text file of the given name
124 * in the given class's package, using the default encoding.
125 * @param resourceName the name of the text file located in the
126 * given class's package.
128 public ResourceReader(Class<?> rootClass, String resourceName) {
129 this.root = rootClass;
130 this.resourceName = resourceName;
131 this.encoding = null;
135 } catch (UnsupportedEncodingException e) {}
139 * Read and return the next line of the file or <code>null</code>
140 * if the end of the file has been reached.
142 public String readLine() throws IOException {
146 String line = reader.readLine();
147 if (line.charAt(0) == '\uFFEF' ||
148 line.charAt(0) == '\uFEFF') {
149 line = line.substring(1);
154 return reader.readLine();
158 * Read a line, ignoring blank lines and lines that start with
160 * @param trim if true then trim leading Pattern_White_Space.
162 public String readLineSkippingComments(boolean trim) throws IOException {
164 String line = readLine();
168 // Skip over white space
169 int pos = PatternProps.skipWhiteSpace(line, 0);
170 // Ignore blank lines and comment lines
171 if (pos == line.length() || line.charAt(pos) == '#') {
175 if (trim) line = line.substring(pos);
182 * Read a line, ignoring blank lines and lines that start with
183 * '#'. Do not trim leading Pattern_White_Space.
185 public String readLineSkippingComments() throws IOException {
186 return readLineSkippingComments(false);
190 * Return the one-based line number of the last line returned by
191 * readLine() or readLineSkippingComments(). Should only be called
192 * after a call to one of these methods; otherwise the return
193 * value is undefined.
195 public int getLineNumber() {
200 * Return a string description of the position of the last line
201 * returned by readLine() or readLineSkippingComments().
203 public String describePosition() {
204 return resourceName + ':' + lineNo;
208 * Reset this reader so that the next call to
209 * <code>readLine()</code> returns the first line of the file
210 * again. This is a somewhat expensive call, however, calling
211 * <code>reset()</code> after calling it the first time does
212 * nothing if <code>readLine()</code> has not been called in
215 public void reset() {
218 } catch (UnsupportedEncodingException e) {}
219 // We swallow this exception, if there is one. If the encoding is
220 // invalid, the constructor will have thrown this exception already and
221 // the caller shouldn't use the object afterwards.
225 * Reset to the start by reconstructing the stream and readers.
226 * We could also use mark() and reset() on the stream or reader,
227 * but that would cause them to keep the stream data around in
228 * memory. We don't want that because some of the resource files
229 * are large, e.g., 400k.
231 private void _reset() throws UnsupportedEncodingException {
235 InputStream is = ICUData.getStream(root, resourceName);
237 throw new IllegalArgumentException("Can't open " + resourceName);
240 InputStreamReader isr =
241 (encoding == null) ? new InputStreamReader(is) :
242 new InputStreamReader(is, encoding);
243 reader = new BufferedReader(isr);