2
2
3
3
import java .io .File ;
4
4
import java .io .IOException ;
5
- import java .nio .ByteBuffer ;
6
- import java .nio .CharBuffer ;
7
5
import java .nio .channels .FileChannel ;
8
6
import java .nio .charset .Charset ;
9
- import java .nio .charset .CharsetDecoder ;
10
- import java .nio .charset .CharsetEncoder ;
11
7
import java .nio .file .Path ;
12
8
import java .nio .file .StandardOpenOption ;
13
- import java .util .ArrayList ;
14
9
15
10
import org .perl6 .nqp .runtime .ExceptionHandling ;
16
11
import org .perl6 .nqp .runtime .ThreadContext ;
17
12
18
- public class FileHandle implements IIOClosable , IIOSeekable , IIOEncodable , IIOSyncReadable , IIOSyncWritable {
19
- private FileChannel chan ;
20
- private CharsetEncoder enc ;
21
- private CharsetDecoder dec ;
22
- private boolean eof = false ;
23
- private ByteBuffer readBuffer ;
13
+ public class FileHandle extends SyncHandle implements IIOSeekable {
14
+
15
+ FileChannel fc ;
24
16
25
17
public FileHandle (ThreadContext tc , String filename , String mode ) {
26
18
try {
27
19
Path p = new File (filename ).toPath ();
28
20
if (mode .equals ("r" )) {
29
- chan = FileChannel .open (p , StandardOpenOption .READ );
21
+ fc = FileChannel .open (p , StandardOpenOption .READ );
30
22
}
31
23
else if (mode .equals ("w" )) {
32
- chan = FileChannel .open (p , StandardOpenOption .WRITE ,
24
+ fc = FileChannel .open (p , StandardOpenOption .WRITE ,
33
25
StandardOpenOption .CREATE ,
34
26
StandardOpenOption .TRUNCATE_EXISTING );
35
27
}
36
28
else if (mode .equals ("wa" )) {
37
- chan = FileChannel .open (p , StandardOpenOption .WRITE ,
29
+ fc = FileChannel .open (p , StandardOpenOption .WRITE ,
38
30
StandardOpenOption .CREATE ,
39
31
StandardOpenOption .APPEND );
40
32
}
41
33
else {
42
34
ExceptionHandling .dieInternal (tc , "Unhandled file open mode '" + mode + "'" );
43
35
}
36
+ chan = fc ;
44
37
setEncoding (tc , Charset .forName ("UTF-8" ));
45
38
} catch (IOException e ) {
46
39
throw ExceptionHandling .dieInternal (tc , e );
47
40
}
48
41
}
49
42
50
- public void close (ThreadContext tc ) {
51
- try {
52
- chan .close ();
53
- } catch (IOException e ) {
54
- throw ExceptionHandling .dieInternal (tc , e );
55
- }
56
- }
57
-
58
43
public void seek (ThreadContext tc , long offset , long whence ) {
59
44
try {
60
45
switch ((int )whence ) {
61
46
case 0 :
62
- chan .position (offset );
47
+ fc .position (offset );
63
48
break ;
64
49
case 1 :
65
- chan .position (chan .position () + offset );
50
+ fc .position (fc .position () + offset );
66
51
break ;
67
52
case 2 :
68
- chan .position (chan .size ());
53
+ fc .position (fc .size ());
69
54
break ;
70
55
default :
71
56
throw ExceptionHandling .dieInternal (tc , "Invalid seek mode" );
@@ -77,151 +62,10 @@ public void seek(ThreadContext tc, long offset, long whence) {
77
62
78
63
public long tell (ThreadContext tc ) {
79
64
try {
80
- long position = chan .position ();
65
+ long position = fc .position ();
81
66
return readBuffer != null ? position - readBuffer .remaining () : position ;
82
67
} catch (IOException e ) {
83
68
throw ExceptionHandling .dieInternal (tc , e );
84
69
}
85
70
}
86
-
87
- public void setEncoding (ThreadContext tc , Charset cs ) {
88
- enc = cs .newEncoder ();
89
- dec = cs .newDecoder ();
90
- }
91
-
92
- public synchronized String slurp (ThreadContext tc ) {
93
- try {
94
- // Read in file.
95
- ArrayList <ByteBuffer > buffers = new ArrayList <ByteBuffer >();
96
- ByteBuffer curBuffer = ByteBuffer .allocate (32768 );
97
- int total = 0 ;
98
- int read ;
99
- if (readBuffer != null ) {
100
- total = readBuffer .limit () - readBuffer .position ();
101
- buffers .add (ByteBuffer .wrap (readBuffer .array (), readBuffer .position (), total ));
102
- readBuffer = null ;
103
- }
104
- while ((read = chan .read (curBuffer )) != -1 ) {
105
- curBuffer .flip ();
106
- buffers .add (curBuffer );
107
- curBuffer = ByteBuffer .allocate (32768 );
108
- total += read ;
109
- }
110
- eof = true ;
111
-
112
- return decodeBuffers (buffers , total );
113
- } catch (IOException e ) {
114
- throw ExceptionHandling .dieInternal (tc , e );
115
- }
116
- }
117
-
118
- public synchronized String readline (ThreadContext tc ) {
119
- try {
120
- boolean foundLine = false ;
121
- ArrayList <ByteBuffer > lineChunks = new ArrayList <ByteBuffer >();
122
- int total = 0 ;
123
-
124
- while (!foundLine ) {
125
- /* Ensure we have a buffer available. */
126
- if (readBuffer == null ) {
127
- readBuffer = ByteBuffer .allocate (32768 );
128
- if (chan .read (readBuffer ) == -1 ) {
129
- /* End of file, so what we have is fine. */
130
- eof = true ;
131
- foundLine = true ;
132
- readBuffer .flip ();
133
- break ;
134
- }
135
- readBuffer .flip ();
136
- }
137
-
138
- /* Look for a line end. */
139
- int start = readBuffer .position ();
140
- int end = start ;
141
- while (!foundLine && end < readBuffer .limit ()) {
142
- if (readBuffer .get (end ) == '\n' )
143
- foundLine = true ;
144
- end ++;
145
- }
146
-
147
- /* Copy what we found into the results. */
148
- byte [] lineBytes = new byte [end - start ];
149
- readBuffer .get (lineBytes );
150
- lineChunks .add (ByteBuffer .wrap (lineBytes ));
151
- total += lineBytes .length ;
152
-
153
- /* If we didn't find a line, will cross chunk boundary. */
154
- if (!foundLine )
155
- readBuffer = null ;
156
- }
157
-
158
- if (lineChunks .size () == 1 )
159
- return dec .decode (lineChunks .get (0 )).toString ();
160
- else
161
- return decodeBuffers (lineChunks , total );
162
- } catch (IOException e ) {
163
- throw ExceptionHandling .dieInternal (tc , e );
164
- }
165
- }
166
-
167
- private String decodeBuffers (ArrayList <ByteBuffer > buffers , int total ) throws IOException {
168
- // Copy to a single buffer and decode (could be smarter, but need
169
- // to be wary as UTF-8 chars may span a buffer boundary).
170
- ByteBuffer allBytes = ByteBuffer .allocate (total );
171
- for (ByteBuffer bb : buffers ) {
172
- int amount = total < bb .limit () ? total : bb .limit ();
173
- allBytes .put (bb .array (), 0 , amount );
174
- total -= amount ;
175
- }
176
- allBytes .rewind ();
177
- return dec .decode (allBytes ).toString ();
178
- }
179
-
180
- public boolean eof (ThreadContext tc ) {
181
- return eof ;
182
- }
183
-
184
- public byte [] read (ThreadContext tc , int bytes ) {
185
- try {
186
- ByteBuffer buffer = ByteBuffer .allocate (bytes );
187
- chan .read (buffer );
188
- buffer .flip ();
189
- byte [] res = new byte [buffer .limit ()];
190
- buffer .get (res );
191
- return res ;
192
- } catch (IOException e ) {
193
- throw ExceptionHandling .dieInternal (tc , e );
194
- }
195
- }
196
-
197
- public void write (ThreadContext tc , byte [] array ) {
198
- ByteBuffer buffer = ByteBuffer .wrap (array );
199
- write (tc , buffer );
200
- }
201
-
202
- protected void write (ThreadContext tc , ByteBuffer buffer ) {
203
- try {
204
- int toWrite = buffer .limit ();
205
- int written = 0 ;
206
- while (written < toWrite ) {
207
- written += chan .write (buffer );
208
- }
209
- } catch (IOException e ) {
210
- throw ExceptionHandling .dieInternal (tc , e );
211
- }
212
- }
213
-
214
- public void print (ThreadContext tc , String s ) {
215
- try {
216
- ByteBuffer buffer = enc .encode (CharBuffer .wrap (s ));
217
- write (tc , buffer );
218
- } catch (IOException e ) {
219
- throw ExceptionHandling .dieInternal (tc , e );
220
- }
221
- }
222
-
223
- public void say (ThreadContext tc , String s ) {
224
- print (tc , s );
225
- print (tc , System .lineSeparator ());
226
- }
227
71
}
0 commit comments