@@ -20,6 +20,7 @@ public class FileHandle implements IIOClosable, IIOSeekable, IIOEncodable, IIOSy
20
20
private CharsetEncoder enc ;
21
21
private CharsetDecoder dec ;
22
22
private boolean eof = false ;
23
+ private ByteBuffer readBuffer ;
23
24
24
25
public FileHandle (ThreadContext tc , String filename , String mode ) {
25
26
try {
@@ -86,34 +87,88 @@ public void setEncoding(ThreadContext tc, Charset cs) {
86
87
dec = cs .newDecoder ();
87
88
}
88
89
89
- public String slurp (ThreadContext tc ) {
90
+ public synchronized String slurp (ThreadContext tc ) {
90
91
try {
91
92
// Read in file.
92
93
ArrayList <ByteBuffer > buffers = new ArrayList <ByteBuffer >();
93
94
ByteBuffer curBuffer = ByteBuffer .allocate (32768 );
94
95
int total = 0 ;
95
96
int read ;
97
+ if (readBuffer != null ) {
98
+ buffers .add (ByteBuffer .wrap (readBuffer .array (), readBuffer .position (),
99
+ readBuffer .limit () - readBuffer .position ()));
100
+ readBuffer = null ;
101
+ }
96
102
while ((read = chan .read (curBuffer )) != -1 ) {
103
+ curBuffer .flip ();
97
104
buffers .add (curBuffer );
98
105
curBuffer = ByteBuffer .allocate (32768 );
99
106
total += read ;
100
107
}
101
108
eof = true ;
102
109
103
- // Copy to a single buffer and decode (could be smarter, but need
104
- // to be wary as UTF-8 chars may span a buffer boundary).
105
- ByteBuffer allBytes = ByteBuffer .allocate (total );
106
- for (ByteBuffer bb : buffers )
107
- allBytes .put (bb .array (), 0 , bb .position ());
108
- allBytes .rewind ();
109
- return dec .decode (allBytes ).toString ();
110
+ return decodeBuffers (buffers , total );
111
+ } catch (IOException e ) {
112
+ throw ExceptionHandling .dieInternal (tc , e );
113
+ }
114
+ }
115
+
116
+ public synchronized String readline (ThreadContext tc ) {
117
+ try {
118
+ boolean foundLine = false ;
119
+ ArrayList <ByteBuffer > lineChunks = new ArrayList <ByteBuffer >();
120
+ int total = 0 ;
121
+
122
+ while (!foundLine ) {
123
+ /* Ensure we have a buffer available. */
124
+ if (readBuffer == null ) {
125
+ readBuffer = ByteBuffer .allocate (32768 );
126
+ if (chan .read (readBuffer ) == -1 ) {
127
+ /* End of file, so what we have is fine. */
128
+ eof = true ;
129
+ foundLine = true ;
130
+ break ;
131
+ }
132
+ readBuffer .flip ();
133
+ }
134
+
135
+ /* Look for a line end. */
136
+ int start = readBuffer .position ();
137
+ int end = start ;
138
+ while (!foundLine && end < readBuffer .limit ()) {
139
+ if (readBuffer .get (end ) == '\n' )
140
+ foundLine = true ;
141
+ end ++;
142
+ }
143
+
144
+ /* Copy what we found into the results. */
145
+ byte [] lineBytes = new byte [end - start ];
146
+ readBuffer .get (lineBytes );
147
+ lineChunks .add (ByteBuffer .wrap (lineBytes ));
148
+ total += lineBytes .length ;
149
+
150
+ /* If we didn't find a line, will cross chunk boundary. */
151
+ if (!foundLine )
152
+ readBuffer = null ;
153
+ }
154
+
155
+ if (lineChunks .size () == 1 )
156
+ return dec .decode (lineChunks .get (0 )).toString ();
157
+ else
158
+ return decodeBuffers (lineChunks , total );
110
159
} catch (IOException e ) {
111
160
throw ExceptionHandling .dieInternal (tc , e );
112
161
}
113
162
}
114
163
115
- public String readline (ThreadContext tc ) {
116
- throw new RuntimeException ("FileHandle.readline() NYI" );
164
+ private String decodeBuffers (ArrayList <ByteBuffer > buffers , int total ) throws IOException {
165
+ // Copy to a single buffer and decode (could be smarter, but need
166
+ // to be wary as UTF-8 chars may span a buffer boundary).
167
+ ByteBuffer allBytes = ByteBuffer .allocate (total );
168
+ for (ByteBuffer bb : buffers )
169
+ allBytes .put (bb .array (), 0 , bb .limit ());
170
+ allBytes .rewind ();
171
+ return dec .decode (allBytes ).toString ();
117
172
}
118
173
119
174
public boolean eof (ThreadContext tc ) {
0 commit comments