-
Notifications
You must be signed in to change notification settings - Fork 292
/
Handle.pod6
1132 lines (834 loc) · 38.7 KB
/
Handle.pod6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
=begin pod :kind("Type") :subkind("class") :category("domain-specific")
=TITLE class IO::Handle
=SUBTITLE Opened file or stream
class IO::Handle { }
Instances of C<IO::Handle> encapsulate an I<handle> to manipulate input/output
resources. Usually there is no need to create directly an C<IO::Handle>
instance, since it will be done by other roles and methods. For instance, an
L<IO::Path|/type/IO::Path> object provides an L<open|/routine/open> method that returns an
C<IO::Handle>:
my $fh = '/tmp/log.txt'.IO.open;
say $fh.^name; # OUTPUT: IO::Handle
The first line is pretty much equivalent to the following piece of code:
my $fh = IO::Handle.new( :path( '/tmp/log.txt'.IO.path ) ).open;
=head1 Methods
=head2 method open
Defined as:
=for code :method
method open(IO::Handle:D:
:$bin, :$enc, :$chomp, :$nl-in, Str:D :$nl-out,
Str :$mode,
:$r, :$w, :$a, :$x, :$update, :$rw, :$rx, :$ra,
:$create, :$append, :$truncate, :$exclusive,
:$out-buffer,
--> IO::Handle:D
)
Opens the handle in one of the modes. L<Fails|/routine/fail> with appropriate
exception if the open fails.
See description of individual methods for the accepted values and behavior of
L«C<:$chomp>|/type/IO::Handle#method_chomp»,
L«C<:$nl-in>|/type/IO::Handle#method_nl-in»,
L«C<:$nl-out>|/type/IO::Handle#method_nl-out», and
L«C<:$enc>|/type/IO::Handle#method_encoding». The values for parameters default
to the invocant's attributes and if any of them are provided, the attributes
will be updated to the new values. Specify C<:$bin> set to C<True> instead of
C<:$enc> to indicate the handle should be opened in binary mode. Specifying
undefined value as C<:$enc> is equivalent to not specifying C<:$enc> at all.
Specifying both a defined encoding as C<:$enc> and C<:$bin> set to true will
cause C<X::IO::BinaryAndEncoding> exception to be thrown.
The open mode defaults to non-exclusive, read only (same as specifying
C<:r>) and can be controlled by a mix of the following arguments:
=begin code :lang<text> :allow< B R >
:r same as specifying :mode<ro> same as specifying nothing
:w same as specifying :mode<wo>, :create, :truncate
:a same as specifying :mode<wo>, :create, :append
:x same as specifying :mode<wo>, :create, :exclusive
:update same as specifying :mode<rw>
:rw same as specifying :mode<rw>, :create
:ra same as specifying :mode<rw>, :create, :append
:rx same as specifying :mode<rw>, :create, :exclusive
=end code
Support for combinations of modes I<other> than what is listed above
is implementation-dependent and should be assumed unsupported. That is,
specifying, for example, C<.open(:r :create)> or
C<.open(:mode<wo> :append :truncate)> might work or might cause the Universe
to implode, depending on a particular implementation. This applies to reads/writes
to a handle opened in such unsupported modes as well.
The mode details are:
=begin code :lang<text> :allow< B R >
:mode<ro> means "read only"
:mode<wo> means "write only"
:mode<rw> means "read and write"
:create means the file will be created, if it does not exist
:truncate means the file will be emptied, if it exists
:exclusive means .open will fail if the file already exists
:append means writes will be done at the end of file's current contents
=end code
Attempts to open a directory, write to a handle opened in read-only mode
or read from a handle opened in write-only mode,
or using text-reading methods on a handle opened in binary mode will
fail or throw.
In B<6.c> language, it's possible to open path C<'-'>, which will cause
C<open> to open (if C<closed>) the C<$*IN> handle if opening in read-only
mode or to open the C<$*OUT> handle if opening in write-only mode. All other
modes in this case will result in exception being thrown.
As of B<6.d> language version, use path C<'-'> is deprecated and it will
be removed in future language versions entirely.
The C<:out-buffer> controls output buffering and by default behaves as if
it were C<Nil>. See method L<out-buffer|/routine/out-buffer> for details.
B<Note (Rakudo versions before 2017.09): Filehandles are NOT flushed or closed
when they go out of scope>. While they I<will> get closed when garbage
collected, garbage collection isn't guaranteed to get run. This means I<you
should> use an explicit C<close> on handles opened for writing, to avoid data
loss, and an explicit C<close> is I<recommended> on handles opened for reading
as well, so that your program does not open too many files at the same time,
triggering exceptions on further C<open> calls.
B<Note (Rakudo versions 2017.09 and after):> Open filehandles are automatically
closed on program exit, but it is still highly recommended that you C<close>
opened handles explicitly.
=head2 method comb
Defined as:
method comb(IO::Handle:D: Bool :$close, |args --> Seq:D)
Read the handle and processes its contents the same way
L«C<Str.comb>|/type/Str#routine_comb» does, taking the same arguments, closing
the handle when done if C<$close> is set to a true value. Implementations may
slurp the file in its entirety when this method is called.
Attempting to call this method when the handle is
L<in binary mode|/type/IO::Handle#method_encoding> will result in
C<X::IO::BinaryMode> exception being thrown.
=for code
my $fh = 'path/to/file'.IO.open;
say "The file has {+$fh.comb: '♥', :close} ♥s in it";
=head2 method chomp
Defined as:
has $.chomp is rw = True
One of the attributes that can be set via C<.new> or L<open|/routine/open>. Defaults to
C<True>. Takes a L<Bool|/type/Bool> specifying whether the line separators (as defined by
L«C<.nl-in>|/type/IO::Handle#method_nl-in») should be removed from content when
using L«C<.get>|/type/IO::Handle#method_get» or
L«C<.lines>|/type/IO::Handle#routine_lines» methods.
=head2 routine get
Defined as:
method get(IO::Handle:D: --> Str:D)
multi sub get (IO::Handle $fh = $*ARGFILES --> Str:D)
Reads a single line of input from the handle, removing the trailing newline
characters (as set by L«C<.nl-in>|/routine/nl-in») if the handle's C<.chomp>
attribute is set to C<True>. Returns C<Nil>, if no more input is available. The
subroutine form defaults to
L«C<$*ARGFILES>|/language/variables#index-entry-%24%2AARGFILES» if no handle is
given.
Attempting to call this method when the handle is
L<in binary mode|/type/IO::Handle#method_encoding> will result in
C<X::IO::BinaryMode> exception being thrown.
=begin code
$*IN.get.say; # Read one line from the standard input
my $fh = open 'filename';
$fh.get.say; # Read one line from a file
$fh.close;
say get; # Read one line from $*ARGFILES
=end code
=head2 routine getc
Defined as:
method getc(IO::Handle:D: --> Str:D)
multi sub getc (IO::Handle $fh = $*ARGFILES --> Str:D)
Reads a single character from the input stream. Attempting to call this method
when the handle is L<in binary mode|/type/IO::Handle#method_encoding> will
result in C<X::IO::BinaryMode> exception being thrown. The subroutine form
defaults to L«C<$*ARGFILES>|/language/variables#index-entry-%24%2AARGFILES» if
no handle is given. Returns C<Nil>, if no more input is available, otherwise
operation will block, waiting for at least one character to be available; these
caveats apply:
=head3 Buffering terminals
Using getc to get a single keypress from a terminal will only work properly if
you've set the terminal to "unbuffered". Otherwise the terminal will wait for
the return key to be struck or the buffer to be filled up before perl6 gets
even a single byte of data.
=head3 Waiting for potential combiners
If your handle's encoding allows combining characters to be read, perl6 will
wait for more data to be available before it provides a character. This means
that inputting an "e" followed by a combining acute will give you an e with an
acute rather than giving an "e" and letting the next reading function give you
a dangling combiner. However, it also means that when the user inputs just an
"e" and has no intention to also input a combining acute, your program will be
waiting for another keypress before the initial "e" is returned.
=head2 submethod DESTROY
Defined as:
submethod DESTROY(IO::Handle:D:)
Closes the filehandle, unless its L<native-descriptor|/routine/native-descriptor> is C<2> or lower. This
ensures the standard filehandles do not get inadvertently closed.
Note that garbage collection is not guaranteed to happen, so you must NOT rely
on C<DESTROY> for closing the handles you I<write to> and instead close them
yourself. Programs that open a lot of files should close the handles explicitly
as well, regardless of whether they were open for writing, since too many files
might get opened before garbage collection happens and the no longer used
handles get closed.
=head2 method gist
Defined as:
method gist(IO::Handle:D: --> Str:D)
Returns a string containing information which
L«C<.path>|/type/IO::Handle#method_path», if any, the handle is created for
and whether it is L«C<.opened>|/type/IO::Handle#method_opened».
=begin code
say IO::Handle.new; # IO::Handle<(Any)>(closed)
say "foo".IO.open; # IO::Handle<"foo".IO>(opened)
=end code
=head2 method eof
Defined as:
method eof(IO::Handle:D: --> Bool:D)
Non-blocking. Returns C<True> if the read operations have exhausted the
contents of the handle. For L<seekable|/routine/seek> handles, this means
current position is at or beyond the end of file and L<seeking|/routine/seek>
an exhausted handle back into the file's contents will result in
L<eof|/routine/eof> returning C<False> again.
On L<non-seekable|/routine/seek> handles and handles opened to zero-size
files (including special files in C</proc/>), EOF won't be set
until a read operation fails to read any bytes. For example, in this code,
the first C<read> consumes all of the data, but it's only until the second
C<read> that reads nothing would the EOF on a TTY handle be set:
=begin code :lang<shell>
$ echo "x" | perl6 -e 'with $*IN { .read: 10000; .eof.say; .read: 10; .eof.say }'
False
True
=end code
=head2 method encoding
Defined as:
multi method encoding(IO::Handle:D: --> Str:D)
multi method encoding(IO::Handle:D: $enc --> Str:D)
Returns a L<Str|/type/Str> representing the encoding currently used by
the handle, defaulting to C<"utf8">. C<Nil> indicates the filehandle is
currently in binary mode. Specifying an optional positional C<$enc> argument
switches the encoding used by the handle; specify C<Nil> as encoding to put the
handle into binary mode.
The accepted values for encoding are case-insensitive. The available encodings
vary by implementation and backend. On Rakudo MoarVM the following are
supported:
X<|windows-1252>X<|windows-1251>X<|windows-932>X<|iso-8859-1>X<|ascii>
=for code :lang<text>
utf8
utf16
utf16le
utf16be
utf8-c8
iso-8859-1
windows-1251
windows-1252
windows-932
ascii
The default encoding is utf8, which undergoes normalization into Unicode B<NFC>
(normalization form canonical). In some cases you may want to ensure no
normalization is done; for this you can use C<utf8-c8>. Before using C<utf8-c8>
please read L<Unicode: Filehandles and I/O|/language/unicode#File_Handles_and_I/O>
for more information on C<utf8-c8> and B<NFC>.
As of Rakudo 2018.04 L<windows-932|https://en.wikipedia.org/wiki/Code_page_932_(Microsoft_Windows)>
is also supported which is a variant of X<ShiftJIS>.
Implementation may choose to also provide support for aliases, e.g. Rakudo
allows aliases C<latin-1> for C<iso-8859-1> encoding and dashed utf versions:
C<utf-8> and C<utf-16>.
=head3 utf16, utf16le and utf16be
X<|utf16-le>X<|utf16-be>X<|utf16>X<|utf-16>
Unlike utf8, utf16 has an
endianness — either big endian or little endian. This relates to the ordering of
bytes. Computer CPUs also have an endianness. Raku's C<utf16> format specifier
will use the endianness of host system when encoding. When decoding it will look
for a byte order mark and if it is there use that to set the endianness. If there
is no byte order mark it will assume the file uses the same endianness as the host
system. A byte order mark is the codepoint U+FEFF which is ZERO WIDTH NO-BREAK
SPACE. On C<utf16> encoded files the standard states if it exists at the start
of a file it shall be interpreted as a byte order mark, not a U+FEFF codepoint.
While writing will cause a different file to be written on different endian
systems, at the release of 2018.10 the byte order mark will be written out when
writing a file and files created with the utf16 encoding will be able to be
read on either big or little endian systems.
When using utf16be or utf16le encodings a byte order mark is B<not> used. The
endianness used is not affected by the host cpu type and is either big endian for
utf16be or little endian for utf16le.
In keeping with the standard, a 0xFEFF byte at the start of a file is interpreted
as a ZERO WIDTH NO-BREAK SPACE and not as a byte order mark. No byte order mark
is written to files that use the utf16be or utf16le encodings.
As of Rakudo 2018.09 on MoarVM, utf16,
X<utf16le> and X<utf16be> are supported. In 2018.10, writing to a file with utf16 will
properly add a byte order mark (BOM).
=head3 Examples
=begin code
with 'foo'.IO {
.spurt: "First line is text, then:\nBinary";
my $fh will leave {.close} = .open;
$fh.get.say; # OUTPUT: «First line is text, then:»
$fh.encoding: Nil;
$fh.slurp.say; # OUTPUT: «Buf[uint8]:0x<42 69 6e 61 72 79>»
}
=end code
=head2 routine lines
Defined as:
sub lines( $what = $*ARGFILES, |c)
method lines( IO::Handle:D: $limit, :$close )
method lines( IO::Handle:D: :$close )
Return a L<Seq|/type/Seq> each element of which is a line from the handle (that is
chunks delineated by L«C<.nl-in>|/type/IO::Handle#method_nl-in»). If the
handle's L«C<.chomp>|/type/IO::Handle#method_chomp» attribute is set to C<True>,
then characters specified by L«C<.nl-in>|/type/IO::Handle#method_nl-in» will be
stripped from each line.
Reads up to C<$limit> lines, where C<$limit> can be a non-negative L<Int|/type/Int>,
C<Inf>, or L<Whatever|/type/Whatever> (which is interpreted to mean C<Inf>). If C<:$close> is
set to C<True>, will close the handle when the file ends or C<$limit> is
reached. Subroutine form defaults to
L«C<$*ARGFILES>|/language/variables#index-entry-%24%2AARGFILES», if no
handle is provided.
Attempting to call this method when the handle is
L<in binary mode|/type/IO::Handle#method_encoding> will result in
C<X::IO::BinaryMode> exception being thrown.
B<NOTE:> the lines are read lazily, so ensure the returned L<Seq|/type/Seq> is either
L<fully reified|/language/glossary#index-entry-Reify> or is no longer needed
when you close the handle or attempt to use any other method that changes the
file position.
=begin code
say "The file contains ",
'50GB-file'.IO.open.lines.grep(*.contains: 'Perl').elems,
" lines that mention Perl";
# OUTPUT: «The file contains 72 lines that mention Perl»
=end code
=head2 method lock
Defined as:
method lock(IO::Handle:D: Bool:D :$non-blocking = False, Bool:D :$shared = False --> True)
Places an advisory lock on the filehandle. If C<:$non-blocking> is C<True>
will L«C<fail>|/routine/fail» with C<X::IO::Lock> if lock could not be
obtained, otherwise will block until the lock can be placed. If C<:$shared>
is C<True> will place a shared (read) lock, otherwise will place an
exclusive (write) lock. On success, returns C<True>; L«fails|/routine/fail»
with C<X::IO::Lock> if lock cannot be placed (e.g. when trying to place
a shared lock on a filehandle opened in write mode or trying to
place an exclusive lock on a filehandle opened in read mode).
You can use C<lock> again to replace an existing lock with another one.
To remove a lock, L«C<close>|/routine/close» the filehandle or use
L«C<unlock>|/routine/unlock».
=begin code
# One program writes, the other reads, and thanks to locks either
# will wait for the other to finish before proceeding to read/write
# Writer
given "foo".IO.open(:w) {
.lock;
.spurt: "I ♥ Raku!";
.close; # closing the handle unlocks it; we could also use `unlock` method for that
}
# Reader
given "foo".IO.open {
.lock: :shared;
.slurp.say; # OUTPUT: «I ♥ Raku!»
.close;
}
=end code
=head2 method unlock
Defined as:
method unlock(IO::Handle:D: --> True)
Removes a L«C<lock>|/routine/lock» from the filehandle.
=head2 routine words
Defined as:
multi sub words(IO::Handle:D $fh = $*ARGFILES, $limit = Inf, :$close --> Seq:D)
multi method words(IO::Handle:D: $limit = Inf, :$close --> Seq:D)
Similar to L«C<Str.words>|/type/Str#routine_words», separates the handle's
stream on contiguous chunks of whitespace (as defined
by Unicode) and returns a L<Seq|/type/Seq> of the resultant "words." Takes an optional
C<$limit> argument that can be a non-negative L<Int|/type/Int>, C<Inf>, or L<Whatever|/type/Whatever>
(which is interpreted to mean C<Inf>), to indicate only up-to C<$limit> words
must be returned. If L<Bool|/type/Bool> C<:$close> named argument is set to C<True>,
will automatically close the handle when the returned L<Seq|/type/Seq> is exhausted.
Subroutine form defaults to
L«C<$*ARGFILES>|/language/variables#index-entry-%24%2AARGFILES», if no handle
is provided.
Attempting to call this method when the handle is
L<in binary mode|/type/IO::Handle#method_encoding> will result in
C<X::IO::BinaryMode> exception being thrown.
=for code
my %dict := bag $*IN.words;
say "Most common words: ", %dict.sort(-*.value).head: 5;
B<NOTE:> implementations may read I<more> data than necessary when a call
to C<.words> is made. That is, C<$handle.words(2)> may read more data than two
"words" worth of data and subsequent calls to read methods might not read from
the place right after the two fetched words. After a call to C<.words>, the
file position should be treated as undefined.
=head2 method split
Defined as:
method split(IO::Handle:D: :$close, |c)
L<Slurps|/routine/slurp> the handle's content and calls
L«C<Str.split>|/type/Str#routine_split» on it, forwarding any of the given
arguments. If C<:$close> named parameter is set to C<True>, will
L<close|/routine/close> the invocant after slurping.
Attempting to call this method when the handle is L<in binary
mode|/type/IO::Handle#method_encoding> will result in C<X::IO::BinaryMode>
exception being thrown.
=for code
my $fh = 'path/to/file'.IO.open;
$fh.split: '♥', :close; # Returns file content split on ♥
=head2 method spurt
Defined as:
multi method spurt(IO::Handle:D: Blob $data, :$close = False)
multi method spurt(IO::Handle:D: Cool $data, :$close = False)
Writes all of the C<$data> into the filehandle, closing it when finished,
if C<$close> is C<True>. For L«C<Cool>|/type/Cool» C<$data>, will use the
encoding the handle is set to use (L«C<IO::Handle.open>|/routine/open»
or L«C<IO::Handle.encoding>|/routine/encoding»).
Behavior for spurting a L«C<Cool>|/type/Cool» when the handle is in binary
mode or spurting a L«C<Blob>|/type/Blob» when the handle is NOT in binary
mode is undefined.
=head2 method print
Defined as:
multi method print(**@text --> True)
multi method print(Junction:D --> True)
Writes the given C<@text> to the handle, coercing any non-L<Str|/type/Str>
objects to L<Str|/type/Str> by calling L«C<.Str>|/routine/Str» method on them.
L<Junction|/type/Junction> arguments
L<autothread|/language/glossary#index-entry-Autothreading> and the order of
printed strings is not guaranteed. See L<write|/routine/write> to write bytes.
Attempting to call this method when the handle is
L<in binary mode|/type/IO::Handle#method_encoding> will result in
C<X::IO::BinaryMode> exception being thrown.
=for code
my $fh = 'path/to/file'.IO.open: :w;
$fh.print: 'some text';
$fh.close;
=head2 method print-nl
Defined as:
method print-nl(IO::Handle:D: --> True)
Writes the value of C<$.nl-out> attribute into the handle. This attribute, by
default, is C<>, but see the L<page on newline|/language/newline> for the rules
it follows in different platforms and environments.
Attempting to call this method when the handle is
L<in binary mode|/type/IO::Handle#method_encoding> will result in
C<X::IO::BinaryMode> exception being thrown.
=for code
my $fh = 'path/to/file'.IO.open: :w, :nl-out("\r\n");
$fh.print: "some text";
$fh.print-nl; # prints \r\n
$fh.close;
=head2 method printf
Defined as:
multi method printf(IO::Handle:D: Cool $format, *@args)
Formats a string based on the given format and arguments and C<.print>s the
result into the filehandle. See
L<sub sprintf|/type/Str#sub_sprintf> for details on
acceptable format directives.
Attempting to call this method when the handle is
L<in binary mode|/type/IO::Handle#method_encoding> will result in
C<X::IO::BinaryMode> exception being thrown.
=for code
my $fh = open 'path/to/file', :w;
$fh.printf: "The value is %d\n", 32;
$fh.close;
=head2 method out-buffer
Defined as:
method out-buffer(--> Int:D) is rw
Controls output buffering and can be set via an argument to L<open|/routine/open>. Takes
an C<int> as the size of the buffer to use (zero is acceptable). Can take
a L<Bool|/type/Bool>: C<True> means to use default, implementation-defined buffer size;
C<False> means to disable buffering (equivalent to using C<0> as buffer size).
Lastly, can take a C<Nil> to enable TTY-based buffering control: if
the handle L<is a TTY|/routine/t>, the buffering is disabled, otherwise,
default, implementation-defined buffer size is used.
See L<flush|/routine/flush> to write out data currently in the buffer. Changing buffer
size flushes the filehandle.
=for code
given 'foo'.IO.open: :w, :1000out-buffer {
.say: 'Hello world!'; # buffered
.out-buffer = 42; # buffer resized; previous print flushed
.say: 'And goodbye';
.close; # closing the handle flushes the buffer
}
=head2 method put
Defined as:
multi method put(**@text --> True)
multi method put(Junction:D --> True)
Writes the given C<@text> to the handle, coercing any non-L<Str|/type/Str> objects to
L<Str|/type/Str> by calling L«C<.Str>|/routine/Str» method on them, and appending the
value of L«C<.nl-out>|/type/IO::Handle#method_nl-out» at the end. L<Junction|/type/Junction>
arguments L<autothread|/language/glossary#index-entry-Autothreading> and the
order of printed strings is not guaranteed.
Attempting to call this method when the handle is
L<in binary mode|/type/IO::Handle#method_encoding> will result in
C<X::IO::BinaryMode> exception being thrown.
=for code
my $fh = 'path/to/file'.IO.open: :w;
$fh.put: 'some text';
$fh.close;
=head2 method say
Defined as:
multi method say(IO::Handle:D: **@text --> True)
This method is identical to L<put|/type/IO::Handle#method_put> except
that it stringifies its arguments by calling L«C<.gist>|/routine/gist» instead
of L«C<.Str>|/routine/Str».
Attempting to call this method when the handle is
L<in binary mode|/type/IO::Handle#method_encoding> will result in
C<X::IO::BinaryMode> exception being thrown.
=for code
my $fh = open 'path/to/file', :w;
$fh.say(Complex.new(3, 4)); # RESULT: «3+4i\n»
$fh.close;
=head2 method read
Defined as:
method read(IO::Handle:D: Int(Cool:D) $bytes = 65536 --> Buf:D)
Binary reading; reads and returns up to C<$bytes> bytes from the filehandle.
C<$bytes> defaults to an implementation-specific value (in Rakudo,
the value of C<$*DEFAULT-READ-ELEMS>, which by default is set to C<65536>).
This method can be called even when the handle is not
L<in binary mode|/type/IO::Handle#method_encoding>.
=begin code
(my $file = 'foo'.IO).spurt: 'I ♥ Perl';
given $file.open {
say .read: 6; # OUTPUT: «Buf[uint8]:0x<49 20 e2 99 a5 20>»
.close;
}
=end code
=head2 method readchars
Defined as:
method readchars(IO::Handle:D: Int(Cool:D) $chars = 65536 --> Str:D)
Reading chars; reads and returns up to C<$chars> chars (graphemes) from the
filehandle. C<$chars> defaults to an implementation-specific value (in Rakudo,
the value of C<$*DEFAULT-READ-ELEMS>, which by default is set to C<65536>).
Attempting to call this method when the handle is
L<in binary mode|/type/IO::Handle#method_encoding> will result in
C<X::IO::BinaryMode> exception being thrown.
=begin code
(my $file = 'foo'.IO).spurt: 'I ♥ Perl';
given $file.open {
say .readchars: 5; # OUTPUT: «I ♥ P»
.close;
}
=end code
=head2 method write
Defined as:
method write(IO::Handle:D: Blob:D $buf --> True)
Writes C<$buf> to the filehandle. This method can be called even when the
handle is not L<in binary mode|/type/IO::Handle#method_encoding>.
X<|SeekFromBeginning>
X<|SeekFromCurrent>
X<|SeekFromEnd>
=head2 method seek
Defined as:
method seek(IO::Handle:D: Int:D $offset, SeekType:D $whence --> True)
Move the file pointer (that is, the position at which any subsequent read
or write operations will begin) to the byte position specified by
C<$offset> relative to the location specified by C<$whence> which may be
one of:
=item C<SeekFromBeginning>: The beginning of the file.
=item C<SeekFromCurrent>: The current position in the file.
=item C<SeekFromEnd>: The end of the file. Please note that you need to specify
a negative offset if you want to position before the end of the file.
=head2 method tell
Defined as:
method tell(IO::Handle:D: --> Int:D)
Return the current position of the file pointer in bytes.
=head2 method slurp-rest
Defined as:
multi method slurp-rest(IO::Handle:D: :$bin! --> Buf)
multi method slurp-rest(IO::Handle:D: :$enc --> Str)
B<DEPRECATION NOTICE:> this method is deprecated in the C<6.d> version. Do
not use it for new code, use L«C<.slurp> method|/routine/slurp» instead.
Returns the remaining content of the file from the current file position (which
may have been set by previous reads or by C<seek>.) If the adverb C<:bin> is
provided a L<Buf|/type/Buf> will be returned; otherwise the return will be a C<Str> with
the optional encoding C<:enc>.
=head2 method slurp
Defined as:
method slurp(IO::Handle:D: :$close, :$bin)
Returns all the content from the current file pointer to the end. If the
invocant is in binary mode or if C<$bin> is set to C<True>, will return a
L<Buf|/type/Buf>, otherwise will decode the content using invocant's current
L«C<.encoding>|/routine/encoding» and return a L<Str|/type/Str>.
If C<:$close> is set to C<True>, will close the handle when finished reading.
B<Note:> On L<Rakudo|/language/glossary#Rakudo> this method was introduced
with release 2017.04; C<$bin> arg was added in 2017.10.
=head2 method Supply
Defined as:
multi method Supply(IO::Handle:D: :$size = 65536)
Returns a C<Supply> that will emit the contents of the handle in chunks.
The chunks will be L«C<Buf>|/type/Buf» if the handle is in binary mode
or, if it isn't, L«C<Str>|/type/Str» decoded using same encoding as
L«C<IO::Handle.encoding>|/routine/encoding».
The size of the chunks is determined by the optional C<:size> named
parameter and C<65536> bytes in binary mode or C<65536> characters in non-binary
mode.
=begin code
"foo".IO.open(:bin).Supply(:size<10>).tap: *.perl.say;
# OUTPUT:
# Buf[uint8].new(73,32,226,153,165,32,80,101,114,108)
# Buf[uint8].new(32,54,33,10)
"foo".IO.open.Supply(:size<10>).tap: *.perl.say;
# OUTPUT:
# "I ♥ Perl"
# " 6!\n"
=end code
=head2 method path
Defined as:
method path(IO::Handle:D:)
For a handle opened on a file this returns the L<IO::Path|/type/IO::Path> that
represents the file. For the standard I/O handles
L«C<$*IN>|/language/variables#index-entry-%24%2AIN»,
L«C<$*OUT>|/language/variables#index-entry-%24%2AOUT», and
L«C<$*ERR>|/language/variables#index-entry-%24%2AERR» it returns an
L<IO::Special|/type/IO::Special> object.
=head2 method IO
Defined as:
method IO(IO::Handle:D:)
Alias for L«C<.path>|/type/IO::Handle#method_path»
=head2 method Str
Returns the value of L«C<.path>|/type/IO::Handle#method_path», coerced
to L<Str|/type/Str>.
=for code
say "foo".IO.open.Str; # OUTPUT: «foo»
=head2 routine close
Defined as:
method close(IO::Handle:D: --> Bool:D)
multi sub close(IO::Handle $fh)
Closes an open filehandle. It's not an error to call C<close> on an
already-closed filehandle. Returns C<True> on success. If you close
one of the standard filehandles (by default: C<$*IN>, C<$*OUT>, or C<$*ERR>),
that is any handle with L<native-descriptor|/routine/native-descriptor> C<2> or lower, you won't be
able to re-open such a handle.
It's a common idiom to use L«C<LEAVE> phaser|/language/phasers#LEAVE» for
closing the handles, which ensures the handle is closed regardless of how the
block is left.
=begin code
do {
my $fh = open "path-to-file";
LEAVE close $fh;
# ... do stuff with the file
}
sub do-stuff-with-the-file (IO $path-to-file) {
my $fh = $path-to-file.open;
# stick a `try` on it, since this will get run even when the sub is
# called with wrong arguments, in which case the `$fh` will be an `Any`
LEAVE try close $fh;
# ... do stuff with the file
}
given "foo/bar".IO.open(:w) {
.spurt: "I ♥ Raku!";
.close;
}
=end code
B<Note:> unlike some other languages, Raku does not use reference counting,
and so B<the filehandles are NOT closed when they go out of scope>. While
they I<will> get closed when garbage collected, garbage collection isn't
guaranteed to get run. This means B<you must> use an explicit C<close> on
handles opened for writing, to avoid data loss, and an explicit C<close>
is I<recommended> on handles opened for reading as well, so that your program
does not open too many files at the same time, triggering exceptions on further
C<open> calls.
Note several methods allow for providing C<:close> argument, to close the handle
after the operation invoked by the method completes. As a simpler alternative,
the L<IO::Path|/type/IO::Path> type provides many reading and writing methods that let you work
with files without dealing with filehandles directly.
=head2 method flush
Defined as:
method flush(IO::Handle:D: --> True)
Will flush the handle, writing any of the buffered data. Returns C<True>
on success; otherwise, L<fails|/routine/fail> with C<X::IO::Flush>.
=begin code
given "foo".IO.open: :w {
LEAVE .close;
.print: 'something';
'foo'.IO.slurp.say; # (if the data got buffered) OUTPUT: «»
.flush; # flush the handle
'foo'.IO.slurp.say; # OUTPUT: «something»
}
=end code
=head2 method native-descriptor
Defined as:
method native-descriptor()
This returns a value that the operating system would understand as a "file
descriptor" and is suitable for passing to a native function that requires a
file descriptor as an argument such as C<fcntl> or C<ioctl>.
=head2 method nl-in
Defined as:
method nl-in(--> Str:D) is rw
One of the attributes that can be set via C<.new> or L<open|/routine/open>.
Defaults to C<["\x0A", "\r\n"]>. Takes either a L<Str|/type/Str> or
L<Array|/type/Array> of C<Str> specifying input line ending(s) for this handle.
If C<.chomp> attribute is set to C<True>, will strip these endings in routines
that C<chomp>, such as L«C<get>|/routine/get» and L«C<lines>|/routine/lines».
=begin code
with 'test'.IO {
.spurt: '1foo2bar3foo'; # write some data into our test file
my $fh will leave {.close} = .open; # can also set .nl-in via .open arg
$fh.nl-in = [<foo bar>]; # set two possible line endings to use;
$fh.lines.say; # OUTPUT: ("1", "2", "3").Seq
}
=end code
=head2 method nl-out
Defined as:
has Str:D $.nl-out is rw = "\n";
One of the attributes that can be set via C<.new> or L<open|/routine/open>.
Defaults to C<"\n">. Takes a L<Str|/type/Str> specifying output line ending for this
handle, to be used by methods L«C<.put>|/type/IO::Handle#method_put»
and L«C<.say>|/type/IO::Handle#method_say».
=begin code
with 'test'.IO {
given .open: :w {
.put: 42;
.nl-out = 'foo';
.put: 42;
.close;
}
.slurp.perl.say; # OUTPUT: «"42\n42foo"»
}
=end code
=head2 method opened
Defined as:
method opened(IO::Handle:D: --> Bool:D)
Returns C<True> if the handle is open, C<False> otherwise.
=head2 method t
X<|tty>
Defined as:
method t(IO::Handle:D: --> Bool:D)
Returns C<True> if the handle is opened to a
L<TTY|https://en.wikipedia.org/wiki/Terminal_emulator>, C<False> otherwise.
=head1 Creating Custom Handles
As of 6.d language (early implementation available in Rakudo compiler
version 2018.08), a few helper methods are available to simplify creation of
custom C<IO::Handle> objects. In your subclass you simply need to implement
those methods to affect all of the related features. If your handle wants
to work with textual read/write methods and doesn't use the standard C<.open>
method, be sure to call C<.encoding> method in your custom handle to get
decoder/encoder properly set up:
=begin code :skip-test<needs ecosystem>
class IO::URL is IO::Handle {
has $.URL is required;
has Buf $!content;
submethod TWEAK {
use WWW; # ecosystem module that will let us `get` a web page
use DOM::Tiny; # ecosystem module that will parse out all text from HTML
$!content := Buf.new: DOM::Tiny.parse(get $!URL).all-text(:trim).encode;
self.encoding: 'utf8'; # set up encoder/decoder
}
method open(|) { self } # block out some IO::Handle methods
method close(|) { self } # that work with normal low-level file
method opened { ! self.EOF } # handles, since we don't. This isn't
method lock(| --> True) { } # necessary, but will make our handle
method unlock( --> True) { } # be more well-behaved if someone
# actually calls one of these methods. There are more of these you
# can handle, such as .tell, .seek, .flush, .native-descriptor, etc.
method WRITE(|) {
# For this handle we'll just die on write. If yours can handle writes.
# The data to write will be given as a Blob positional argument.
die "Cannot write into IO::URL";
}
method READ(\bytes) {
# We splice off the requested number of bytes from the head of
# our content Buf. The handle's decoder will handle decoding them
# automatically, if textual read methods were called on the handle.
$!content.splice: 0, bytes
}
method EOF {
# For "end of file", we'll simply report whether we still have
# any bytes of the website we fetched on creation.
not $!content
}
}
my $fh := IO::URL.new: :URL<raku.org>;
# .slurp and print all the content from the website. We can use all other
# read methods, such as .lines, or .get, or .readchars. All of them work
# correctly, even though we only defined .READ and .EOF
$fh.slurp.say;
=end code
=head2 method WRITE
Defined as: