1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.yaml.snakeyaml.reader;
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 import java.io.IOException;
41 import java.io.InputStream;
42 import java.io.InputStreamReader;
43 import java.io.PushbackInputStream;
44 import java.io.Reader;
45 import java.nio.charset.Charset;
46 import java.nio.charset.CharsetDecoder;
47 import java.nio.charset.CodingErrorAction;
48
49
50
51
52
53 public class UnicodeReader extends Reader {
54 private static final Charset UTF8 = Charset.forName("UTF-8");
55 private static final Charset UTF16BE = Charset.forName("UTF-16BE");
56 private static final Charset UTF16LE = Charset.forName("UTF-16LE");
57
58 PushbackInputStream internalIn;
59 InputStreamReader internalIn2 = null;
60
61 private static final int BOM_SIZE = 3;
62
63
64
65
66
67 public UnicodeReader(InputStream in) {
68 internalIn = new PushbackInputStream(in, BOM_SIZE);
69 }
70
71
72
73
74
75 public String getEncoding() {
76 return internalIn2.getEncoding();
77 }
78
79
80
81
82
83 protected void init() throws IOException {
84 if (internalIn2 != null)
85 return;
86
87 Charset encoding;
88 byte bom[] = new byte[BOM_SIZE];
89 int n, unread;
90 n = internalIn.read(bom, 0, bom.length);
91
92 if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) && (bom[2] == (byte) 0xBF)) {
93 encoding = UTF8;
94 unread = n - 3;
95 } else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) {
96 encoding = UTF16BE;
97 unread = n - 2;
98 } else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) {
99 encoding = UTF16LE;
100 unread = n - 2;
101 } else {
102
103 encoding = UTF8;
104 unread = n;
105 }
106
107 if (unread > 0)
108 internalIn.unread(bom, (n - unread), unread);
109
110
111 CharsetDecoder decoder = encoding.newDecoder().onUnmappableCharacter(
112 CodingErrorAction.REPORT);
113 internalIn2 = new InputStreamReader(internalIn, decoder);
114 }
115
116 public void close() throws IOException {
117 init();
118 internalIn2.close();
119 }
120
121 public int read(char[] cbuf, int off, int len) throws IOException {
122 init();
123 return internalIn2.read(cbuf, off, len);
124 }
125 }