1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.csv;
19
20 import static org.apache.commons.csv.Constants.CR;
21 import static org.apache.commons.csv.Constants.LF;
22 import static org.apache.commons.csv.Constants.UNDEFINED;
23 import static org.apache.commons.io.IOUtils.EOF;
24
25 import java.io.IOException;
26 import java.io.Reader;
27
28 import org.apache.commons.io.IOUtils;
29 import org.apache.commons.io.input.UnsynchronizedBufferedReader;
30
31
32
33
34
35
36
37
38 final class ExtendedBufferedReader extends UnsynchronizedBufferedReader {
39
40
41 private int lastChar = UNDEFINED;
42 private int lastCharMark = UNDEFINED;
43
44
45 private long lineNumber;
46 private long lineNumberMark;
47
48
49 private long position;
50 private long positionMark;
51
52
53
54
55 ExtendedBufferedReader(final Reader reader) {
56 super(reader);
57 }
58
59
60
61
62
63
64
65 @Override
66 public void close() throws IOException {
67
68 lastChar = EOF;
69 super.close();
70 }
71
72
73
74
75
76
77
78
79
80 int getLastChar() {
81 return lastChar;
82 }
83
84
85
86
87
88
89 long getLineNumber() {
90
91 if (lastChar == CR || lastChar == LF || lastChar == UNDEFINED || lastChar == EOF) {
92 return lineNumber;
93 }
94 return lineNumber + 1;
95 }
96
97
98
99
100
101
102 long getPosition() {
103 return this.position;
104 }
105
106 @Override
107 public void mark(final int readAheadLimit) throws IOException {
108 lineNumberMark = lineNumber;
109 lastCharMark = lastChar;
110 positionMark = position;
111 super.mark(readAheadLimit);
112 }
113
114 @Override
115 public int read() throws IOException {
116 final int current = super.read();
117 if (current == CR || current == LF && lastChar != CR ||
118 current == EOF && lastChar != CR && lastChar != LF && lastChar != EOF) {
119 lineNumber++;
120 }
121 lastChar = current;
122 position++;
123 return lastChar;
124 }
125
126 @Override
127 public int read(final char[] buf, final int offset, final int length) throws IOException {
128 if (length == 0) {
129 return 0;
130 }
131 final int len = super.read(buf, offset, length);
132 if (len > 0) {
133 for (int i = offset; i < offset + len; i++) {
134 final char ch = buf[i];
135 if (ch == LF) {
136 if (CR != (i > offset ? buf[i - 1] : lastChar)) {
137 lineNumber++;
138 }
139 } else if (ch == CR) {
140 lineNumber++;
141 }
142 }
143 lastChar = buf[offset + len - 1];
144 } else if (len == EOF) {
145 lastChar = EOF;
146 }
147 position += len;
148 return len;
149 }
150
151
152
153
154
155
156
157
158
159
160
161
162
163 @Override
164 public String readLine() throws IOException {
165 if (peek() == EOF) {
166 return null;
167 }
168 final StringBuilder buffer = new StringBuilder();
169 while (true) {
170 final int current = read();
171 if (current == CR) {
172 final int next = peek();
173 if (next == LF) {
174 read();
175 }
176 }
177 if (current == EOF || current == LF || current == CR) {
178 break;
179 }
180 buffer.append((char) current);
181 }
182 return buffer.toString();
183 }
184
185 @Override
186 public void reset() throws IOException {
187 lineNumber = lineNumberMark;
188 lastChar = lastCharMark;
189 position = positionMark;
190 super.reset();
191 }
192
193 }