CINXE.COM

Input/Output the definitive guide | Raku Documentation

<!DOCTYPE html> <html lang="en" class="fontawesome-i2svg-active fontawesome-i2svg-complete" style="scroll-padding-top:60px"> <head> <title>Input/Output the definitive guide | Raku Documentation</title> <meta charset="UTF-8" /> <link href="/assets/images/Camelia.ico" rel="icon" type="image/x-icon"/> <link rel="stylesheet" href="/assets/css/Website.css"/> <link rel="stylesheet" href="/assets/css/typegraph-styling.css"/> <link rel="stylesheet" href="/assets/css/typegraph-dark.css" title="dark"/> <link rel="stylesheet" href="/assets/css/typegraph-light.css" title="light"/> <link rel="stylesheet" href="/assets/css/css/filtered-toc-dark.css" title="dark"/> <link rel="stylesheet" href="/assets/css/css/filtered-toc-light.css" title="light"/> <link rel="stylesheet" href="/assets/css/css/announce-light.css" title="light"/> <link rel="stylesheet" href="/assets/css/css/announce-dark.css" title="dark"/> <link rel="stylesheet" href="/assets/css/all.min.css"/> <link rel="stylesheet" href="/assets/css/listf-styling-light.css" title="light"/> <link rel="stylesheet" href="/assets/css/listf-styling-dark.css" title="dark"/> <link rel="stylesheet" href="/assets/css/css/options-search-light.css" title="light"/> <link rel="stylesheet" href="/assets/css/css/options-search-dark.css" title="dark"/> <link rel="stylesheet" href="/assets/css/css/page-styling-main.css"/> <link rel="stylesheet" href="/assets/css/css/page-styling-dark.css" title="dark"/> <link rel="stylesheet" href="/assets/css/css/page-styling-light.css" title="light"/> <link rel="stylesheet" href="/assets/css/css/chyronToggle-dark.css" title="dark"/> <link rel="stylesheet" href="/assets/css/css/chyronToggle-light.css" title="light"/> <link rel="stylesheet" href="/assets/css/css/centreToggle-dark.css" title="dark"/> <link rel="stylesheet" href="/assets/css/css/centreToggle-light.css" title="light"/> <link rel="stylesheet" href="/assets/css/tm-styling.css"/> <link rel="stylesheet" href="/assets/css/tm-light.css" title="light"/> <link rel="stylesheet" href="/assets/css/tm-dark.css" title="dark"/> <link rel="stylesheet" href="/assets/css/css/rainbow-dark.css" title="dark"/> <link rel="stylesheet" href="/assets/css/css/rainbow-light.css" title="light"/> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@10.2.7/dist/css/autoComplete.min.css" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-light.min.css" title="light" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css" title="dark" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="/assets/scripts/all.min.js"></script><script src="/assets/scripts/filter-script.js"></script><script src="/assets/scripts/tableManager.js"></script><script src="https://cdn.jsdelivr.net/npm/fuzzysort@2.0.4/fuzzysort.min.js"></script><script src="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@10.2.7/dist/autoComplete.min.js"></script><script src="/assets/scripts/filtered-toc.js"></script><script src="/assets/scripts/options-search.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/haskell.min.js"></script><script src="/assets/scripts/page-styling.js"></script><script src="/assets/scripts/announcements.js"></script><script src="/assets/scripts/rainbow.js"></script> </head> <body class="has-navbar-fixed-top"> <div id="Input/Output_the_definitive_guide" class="top-of-page"></div> <nav class="navbar is-fixed-top is-flex-touch" role="navigation" aria-label="main navigation"> <div class="navbar-item" style="margin-left: auto;"> <div class="left-bar-toggle" title="Toggle Table of Contents & Index"> <label class="chyronToggle left"> <input id="navbar-left-toggle" type="checkbox"> <span class="text">Contents</span> </label> </div> </div> <div class="container is-justify-content-space-around"> <div class="navbar-brand"> <div class="navbar-logo"> <a class="navbar-item" href="/"> <img src="/assets/images/camelia-recoloured.png" alt="Raku" width="52.83" height="38"> </a> <span class="navbar-logo-tm">tm</span> </div> <a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" data-target="navMenu"> <span aria-hidden="true"></span> <span aria-hidden="true"></span> <span aria-hidden="true"></span> </a> </div> <div id="navMenu" class="navbar-menu"> <div class="navbar-start"> <a class="navbar-item" href="/introduction" title="Getting started, Tutorials, Migration guides"> Introduction </a> <a class="navbar-item" href="/reference" title="Fundamentals, General reference"> Reference </a> <a class="navbar-item" href="/miscellaneous" title="Programs, Experimental"> Miscellaneous </a> <a class="navbar-item" href="/types" title="The core types (classes) available"> Types </a> <a class="navbar-item" href="/routines" title="Searchable table of routines"> Routines </a> <a class="navbar-item" href="https://raku.org" title="Home page for community"> Raku<sup>®</sup> </a> <a class="navbar-item" href="https://web.libera.chat/#raku" title="IRC live chat"> Chat </a> <div class="navbar-item has-dropdown is-hoverable"> <a class="navbar-link"> More </a> <div class="navbar-dropdown is-right is-rounded"> <hr class="navbar-divider"> <a class="navbar-item js-modal-trigger" data-target="download-ebook"> Download E-Book (epub) </a> <hr class="navbar-divider"> <a class="navbar-item" href="/about"> About </a> <hr class="navbar-divider"> <a class="navbar-item has-text-red" href="https://github.com/raku/doc-website/issues"> Report an issue with this site </a> <hr class="navbar-divider"> <a class="navbar-item" href="https://github.com/raku/doc/issues"> Report an issue with the documentation content </a> <hr class="navbar-divider"> <label class="navbar-item centreToggle" title="Enable/Disable Announcements" style="--switch-width: 18"> <input id="cancelAnnouncements" type="checkbox"> <span class="text">Announcements</span> <span class="on">suppressed</span> <span class="off">allowed</span> </label> </div> </div> </div> <div class="navbar-end navbar-search-wrapper"> <div class="navbar-item"> <div class="field has-addons"> <div class="autoComplete_options"> <input class="control input" id="autoComplete" type="search" dir="ltr" spellcheck=false autocorrect="off" autocomplete="off" autocapitalize="off" placeholder="🔍 Type f to search for ..."> </div> <div class="control" title="Search options"> <a class="button is-primary js-modal-trigger" data-target="options-search-info"> <span class="icon"> <i class="fas fa-cogs"></i> </span> </a> </div> </div> </div> </div> <div id="options-search-info" class="modal"> <div class="modal-background"></div> <div class="modal-content"> <div class="box"> <p>The last search was: <span id="selected-candidate" class="ss-selected"></span></p> <div class="control is-grouped is-grouped-centered options-search-controls"> <label class="centreToggle" title="Include extra information (Alt-E)" style="--switch-width: 10.5"> <input id="options-search-extra" type="checkbox"> <span class="text">Extra info</span> <span class="on">yes</span> <span class="off">no</span> </label> <p>The search response can be shortened by excluding the extra information line (Alt-E)</p> <label class="centreToggle" title="Search engine type Strict/Loose (Alt-L)" style="--switch-width: 10.5"> <input id="options-search-loose" type="checkbox"> <span class="text">Search type</span> <span class="on">loose</span> <span class="off">strict</span> </label> <p> The search engine can perform a strict search (only the characters in the search box) or a loose search (Alt-L)</p> <label class="centreToggle" title="Search in headings (Alt-H)" style="--switch-width: 10.5"> <input id="options-search-headings" type="checkbox"> <span class="text">Headings</span> <span class="on">yes</span> <span class="off">no</span> </label> <p>Search through headings in all web-pages (Alt-H)</p> <label class="centreToggle" title="Search indexed items (Alt-I)" style="--switch-width: 10.5"> <input id="options-search-indexed" type="checkbox"> <span class="text">Indexed</span> <span class="on">yes</span> <span class="off">no</span> </label> <p>Search through all indexed items (Alt-I)</p> <label class="centreToggle" title="Search composite pages (Alt-C)" style="--switch-width: 10.5"> <input id="options-search-composite" type="checkbox"> <span class="text">Composite</span> <span class="on">yes</span> <span class="off">no</span> </label> <p>Search in the names of composite pages, which combine similar information from the main web pages (Alt-C)</p> <label class="centreToggle" title="Search primary sources (Alt-P)" style="--switch-width: 10.5"> <input id="options-search-primary" type="checkbox"> <span class="text">Primary</span> <span class="on">yes</span> <span class="off">no</span> </label> <p>Search through the names of the main web pages (Alt-P)</p> <label class="centreToggle" title="Open in new tab (Alt-Q)" style="--switch-width: 10.5"> <input id="options-search-newtab" type="checkbox"> <span class="text">New tab</span> <span class="on">yes</span> <span class="off">no</span> </label> <p>Once a search candidate has been chosen, it can be opened in a new tab or in the current tab (Alt-Q)</p> <p>If all else fails, an item is added to use the Google search engine on the whole site</p> <button class="button is-warning" id="options-search-reset-defaults">Clear options, reset to defaults</button> <p>Exit this page by pressing &lt;Escape&gt;, or clicking on X or on the background.</p> </div> </div> </div> <button class="modal-close is-large" aria-label="close"></button> </div> </div> <div id="download-ebook" class="modal"> <div class="modal-background"></div> <div class="modal-content"> <div class="box"> <p><a href="/RakuDocumentation.epub" download>RakuDocumentation.epub</a> is a work in progress e-book. It targets the <a href="https://www.w3.org/publishing/epub3/">EPUB v3 specification</a>. It needs testing on a variety of ereaders (some of which may still implicitly expect compliance with EPUB v2). The CSS definitely needs enhancing (especially for code snippets). The Ebook opens in a Calibre reader, which is available on all operating systems.</p> <p>Suggestions are welcome and should be addressed by opening an issue on the Raku/doc-website repository</p> <p>Exit this popup by pressing &lt;Escape&gt;, or clicking on X or on the background.</p> </div> </div> <button class="modal-close is-large" aria-label="close"></button> </div> <div id="announcement-modal" class="modal"> <div class="modal-background"></div> <div class="modal-content"> <div class="box"> <div id="raku-doc-announcement"></div> <p>For more see <a href="/announcements">Announcements page</a>.</p> <p>Exit this popup by pressing &lt;Escape&gt;, or clicking on X or on the background.</p> </div> </div> <button class="modal-close is-large" aria-label="close"></button> </div> </div> </nav> <div class="tile is-ancestor section"> <div class="page-edit"> <a class="button page-edit-button" href="https://github.com/Raku/doc/edit/main/doc/Language/io-guide.rakudoc" title="Edit this page.&#13;Commit: 2da8bda47 2024-07-23"> <span class="icon is-right"> <i class="fas fa-pen-alt is-medium"></i> </span> </a> </div> <div id="left-column" class="tile is-parent is-2 is-hidden"> <div id="left-col-inner"> <div class="tabs" id="tabs"> <ul> <li class="is-active" id="toc-tab"> <a>Table of Contents</a> </li> <li id="index-tab"> <a>Index</a> </li> </ul> </div> <div class="field"> <div class="control has-icons-right"> <input id="toc-filter" class="input" type="text" placeholder="Filter"> <span class="icon is-right has-text-grey"> <i class="fas fa-search is-medium"></i> </span> </div> </div> <div class="raku-sidebar"> <aside id="toc-menu" class="menu"> <ul class="menu-list"> <li><a href="#The_basics">The basics</a></li> <li><a href="#Navigating_paths">Navigating paths</a></li> <ul> <li><a href="#What's_an_IO::Path_anyway?">What's an IO::Path anyway?</a></li> <li><a href="#Path_parts">Path parts</a></li> <li><a href="#Working_with_files">Working with files</a></li> <ul> <li><a href="#Writing_into_files">Writing into files</a></li> <ul> <li><a href="#Writing_new_content">Writing new content</a></li> <li><a href="#Appending_content">Appending content</a></li> </ul> <li><a href="#Reading_from_files">Reading from files</a></li> <ul> <li><a href="#Using_IO::Path">Using IO::Path</a></li> <li><a href="#Using_IO::Handle">Using IO::Handle</a></li> </ul> </ul> </ul> <li><a href="#The_wrong_way_to_do_things">The wrong way to do things</a></li> <ul> <li><a href="#Leave_$*SPEC_alone">Leave $*SPEC alone</a></li> <li><a href="#Stringifying_IO::Path">Stringifying IO::Path</a></li> <li><a href="#Be_mindful_of_$*CWD">Be mindful of $*CWD</a></li> <ul> <li><a href="#temp_the_$*CWD">temp the $*CWD</a></li> </ul> </aside> <aside id="index-menu" class="menu is-hidden"> </aside> </div> </div> </div> <div id="main-column" class="tile is-parent" style="overflow-x: hidden;"> <div id="main-col-inner"> <section class="raku page-header"> <div class="container px-4"> <div class="raku page-title has-text-centered"> Input/Output the definitive guide </div> <div class="raku page-subtitle has-text-centered"> <p>Correctly use Raku IO</p> </div> </div> </section> <section class="raku page-content"><div class="container px-4"><div class="columns one-col"> <h1 id="The_basics" class="raku-h1"><a href="#Input/Output_the_definitive_guide" title="go to top of document">The basics<a class="raku-anchor" title="direct link" href="#The_basics">§</a></a></h1> <p>The vast majority of common IO work is done by the <a href="/type/IO/Path"><code>IO::Path</code></a> type. If you want to read from or write to a file in some form or shape, this is the class you want. It abstracts away the details of filehandles (or &quot;file descriptors&quot;) and so you mostly don't even have to think about them.</p><p>Behind the scenes, <a href="/type/IO/Path"><code>IO::Path</code></a> works with <a href="/type/IO/Handle"><code>IO::Handle</code></a>, a class which you can use directly if you need a bit more control than what <a href="/type/IO/Path"><code>IO::Path</code></a> provides. When working with other processes, e.g. via <a href="/type/Proc"><code>Proc</code></a> or <a href="/type/Proc/Async"><code>Proc::Async</code></a> types, you'll also be dealing with a <em>subclass</em> of <a href="/type/IO/Handle"><code>IO::Handle</code></a>: the <a href="/type/IO/Pipe"><code>IO::Pipe</code></a>.</p><p>Lastly, you have the <a href="/type/IO/CatHandle"><code>IO::CatHandle</code></a>, as well as <a href="/type/IO/Spec"><code>IO::Spec</code></a> and its subclasses, that you'll rarely, if ever, use directly. These classes give you advanced features, such as operating on multiple files as one handle, or low-level path manipulations.</p><p>Along with all these classes, Raku provides several subroutines that let you indirectly work with these classes. These come in handy if you like functional programming style or in Raku one liners.</p><p>While <a href="/type/IO/Socket"><code>IO::Socket</code></a> and its subclasses also have to do with Input and Output, this guide does not cover them.</p> <h1 id="Navigating_paths" class="raku-h1"><a href="#Input/Output_the_definitive_guide" title="go to top of document">Navigating paths<a class="raku-anchor" title="direct link" href="#Navigating_paths">§</a></a></h1> <h2 id="What's_an_IO::Path_anyway?" class="raku-h2"><a href="#Input/Output_the_definitive_guide" title="go to top of document">What's an IO::Path anyway?<a class="raku-anchor" title="direct link" href="#What's_an_IO::Path_anyway?">§</a></a></h2> <p>To represent paths as either files or directories, use <a href="/type/IO/Path"><code>IO::Path</code></a> type. The simplest way to obtain an object of that type is to coerce a <a href="/type/Str"><code>Str</code></a> by calling the <a href="/routine/IO"><code>.IO</code></a> method on it:</p> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights"><span class="highlite-ROUTINE">say</span> <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING">my-file.txt</span><span class="highlite-STRING_DELIMITER">'</span>.<span class="highlite-TYPE">IO</span>; <span class="highlite-COMMENT"># OUTPUT: «&quot;my-file.txt&quot;.IO␤»</span></pre> </div> </div> <p>It may seem like something is missing here—there is no volume or absolute path involved—but that information is actually present in the object. You can see it by using <a href="/routine/raku"><code>.raku</code></a> method:</p> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights"><span class="highlite-ROUTINE">say</span> <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING">my-file.txt</span><span class="highlite-STRING_DELIMITER">'</span>.<span class="highlite-TYPE">IO</span>.<span class="highlite-ROUTINE">raku</span>; <span class="highlite-COMMENT"># OUTPUT: «IO::Path.new(&quot;my-file.txt&quot;, :SPEC(IO::Spec::Unix), :CWD(&quot;/home/camelia&quot;))␤»</span></pre> </div> </div> <p>The two extra attributes—<code>SPEC</code> and <code>CWD</code>—specify what type of operating system semantics the path should use as well as the &quot;current working directory&quot; for the path, i.e. if it's a relative path, then it's relative to that directory.</p><p>This means that regardless of how you made one, an <a href="/type/IO/Path"><code>IO::Path</code></a> object technically always refers to an absolute path. This is why its <a href="/routine/absolute"><code>.absolute</code></a> and <a href="/routine/relative"><code>.relative</code></a> methods return <a href="/type/Str"><code>Str</code></a> objects and they are the correct way to stringify a path.</p><p>However, don't be in a rush to stringify anything. Pass paths around as <a href="/type/IO/Path"><code>IO::Path</code></a> objects. All the routines that operate on paths can handle them, so there's no need to convert them.</p> <h2 id="Path_parts" class="raku-h2"><a href="#Input/Output_the_definitive_guide" title="go to top of document">Path parts<a class="raku-anchor" title="direct link" href="#Path_parts">§</a></a></h2> <p>Given a local file name, it's very easy to get its components. For example, we have a file, &quot;financial.data&quot;, in some directory, &quot;/usr/local/data&quot;. Use Raku to analyze its path:</p> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights"><span class="highlite-KEYWORD">my</span> <span class="highlite-NAME_SCALAR">$fname</span> <span class="highlite-OPERATOR">=</span> <span class="highlite-STRING_DELIMITER">&quot;</span><span class="highlite-STRING">financial.data</span><span class="highlite-STRING_DELIMITER">&quot;</span>; <span class="highlite-COMMENT"># Stringify the full path name </span><span class="highlite-KEYWORD">my</span> <span class="highlite-NAME_SCALAR">$f</span> <span class="highlite-OPERATOR">=</span> <span class="highlite-NAME_SCALAR">$fname</span>.<span class="highlite-TYPE">IO</span>.<span class="highlite-ROUTINE">absolute</span>; <span class="highlite-ROUTINE">say</span> <span class="highlite-NAME_SCALAR">$f</span>; <span class="highlite-COMMENT"># OUTPUT: «/usr/local/data/financial.data␤» </span><span class="highlite-COMMENT"># Stringify the path's parts: </span><span class="highlite-ROUTINE">say</span> <span class="highlite-NAME_SCALAR">$f</span>.<span class="highlite-TYPE">IO</span>.<span class="highlite-ROUTINE">dirname</span>; <span class="highlite-COMMENT"># OUTPUT: «/usr/local/data␤» </span><span class="highlite-ROUTINE">say</span> <span class="highlite-NAME_SCALAR">$f</span>.<span class="highlite-TYPE">IO</span>.<span class="highlite-ROUTINE">basename</span>; <span class="highlite-COMMENT"># OUTPUT: «financial.data␤» </span><span class="highlite-COMMENT"># And the basename's parts: </span><span class="highlite-COMMENT"># Use a method for the extension: </span><span class="highlite-ROUTINE">say</span> <span class="highlite-NAME_SCALAR">$f</span>.<span class="highlite-TYPE">IO</span>.<span class="highlite-ROUTINE">extension</span>; <span class="highlite-COMMENT"># OUTPUT: «data␤» </span><span class="highlite-COMMENT"># Remove the extension by redefining it: </span><span class="highlite-ROUTINE">say</span> (<span class="highlite-NAME_SCALAR">$f</span>.<span class="highlite-TYPE">IO</span>.<span class="highlite-ROUTINE">extension</span>(<span class="highlite-STRING_DELIMITER">&quot;</span><span class="highlite-STRING_DELIMITER">&quot;</span>)).<span class="highlite-TYPE">IO</span>.<span class="highlite-ROUTINE">basename</span>; <span class="highlite-COMMENT"># OUTPUT: «financial␤» </span></pre> </div> </div> <h2 id="Working_with_files" class="raku-h2"><a href="#Input/Output_the_definitive_guide" title="go to top of document">Working with files<a class="raku-anchor" title="direct link" href="#Working_with_files">§</a></a></h2> <h3 id="Writing_into_files" class="raku-h3"><a href="#Input/Output_the_definitive_guide" title="go to top of document">Writing into files<a class="raku-anchor" title="direct link" href="#Writing_into_files">§</a></a></h3> <h4 id="Writing_new_content" class="raku-h4"><a href="#Input/Output_the_definitive_guide" title="go to top of document">Writing new content<a class="raku-anchor" title="direct link" href="#Writing_new_content">§</a></a></h4> <p>Let's make some files and write and read data from them! The <a href="/routine/spurt"><code>spurt</code></a> and <a href="/routine/slurp"><code>slurp</code></a> routines write and read the data in one chunk respectively. Unless you're working with very large files that are difficult to store entirely in memory all at the same time, these two routines are for you.</p> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights"><span class="highlite-STRING_DELIMITER">&quot;</span><span class="highlite-STRING">my-file.txt</span><span class="highlite-STRING_DELIMITER">&quot;</span>.<span class="highlite-TYPE">IO</span>.spurt: <span class="highlite-STRING_DELIMITER">&quot;</span><span class="highlite-STRING">I ♥ Raku!</span><span class="highlite-STRING_DELIMITER">&quot;</span>; </pre> </div> </div> <p>The code above creates a file named <code>my-file.txt</code> in the current directory and then writes text <code>I ♥ Raku!</code> into it. If Raku is your first language, celebrate your accomplishment! Try to open the file you created with a text editor to verify what you wrote with your program. If you already know some other language, you may be wondering if this guide missed anything like handling encoding or error conditions.</p><p>However, that is all the code you need. The string will be encoded in <code>utf-8</code> encoding by default and the errors are handled via the <a href="/type/Failure"><code>Failure</code></a> mechanism: these are exceptions you can handle using regular conditionals. In this case, we're letting all potential <a href="/type/Failure"><code>Failure</code></a>s get sunk after the call and so any <a href="/type/Exception"><code>Exceptions</code></a> they contain will be thrown.</p> <h4 id="Appending_content" class="raku-h4"><a href="#Input/Output_the_definitive_guide" title="go to top of document">Appending content<a class="raku-anchor" title="direct link" href="#Appending_content">§</a></a></h4> <p>If you wanted to add more content to the file we created in the previous section, you could note the <a href="/routine/spurt"><code>spurt</code> documentation</a> mentions <code>:append</code> as one of its argument options. However, for finer control, let's get ourselves an <a href="/type/IO/Handle"><code>IO::Handle</code></a> to work with:</p> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights"><span class="highlite-KEYWORD">my</span> <span class="highlite-NAME_SCALAR">$fh</span> <span class="highlite-OPERATOR">=</span> <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING">my-file.txt</span><span class="highlite-STRING_DELIMITER">'</span>.<span class="highlite-TYPE">IO</span>.open: :a; <span class="highlite-NAME_SCALAR">$fh</span>.print: <span class="highlite-STRING_DELIMITER">&quot;</span><span class="highlite-STRING">I count: </span><span class="highlite-STRING_DELIMITER">&quot;</span>; <span class="highlite-NAME_SCALAR">$fh</span>.print: <span class="highlite-STRING_DELIMITER">&quot;</span><span class="highlite-NAME_SCALAR">$_</span><span class="highlite-STRING"> </span><span class="highlite-STRING_DELIMITER">&quot;</span> <span class="highlite-KEYWORD">for</span> ^10; <span class="highlite-NAME_SCALAR">$fh</span>.<span class="highlite-ROUTINE">close</span>; </pre> </div> </div> <p>The <a href="/routine/open"><code>.open</code></a> method call opens our <a href="/type/IO/Path"><code>IO::Path</code></a> and returns an <a href="/type/IO/Handle"><code>IO::Handle</code></a>. We passed <code>:a</code> as argument, to indicate we want to open the file for writing in append mode.</p><p>In the next two lines of code, we use the usual <a href="/routine/print"><code>.print</code></a> method on that <a href="/type/IO/Handle"><code>IO::Handle</code></a> to print a line with 11 pieces of text (the <code>'I count: '</code> string and 10 numbers). Note that, once again, <a href="/type/Failure"><code>Failure</code></a> mechanism takes care of all the error checking for us. If the <a href="/routine/open"><code>.open</code></a> fails, it returns a <a href="/type/Failure"><code>Failure</code></a>, which will throw when we attempt to call method the <a href="/routine/print"><code>.print</code></a> on it.</p><p>Finally, we close the <a href="/type/IO/Handle"><code>IO::Handle</code></a> by calling the <a href="/routine/close"><code>.close</code></a> method on it. It is <em>important that you do it</em>, especially in large programs or ones that deal with a lot of files, as many systems have limits to how many files a program can have open at the same time. If you don't close your handles, eventually you'll reach that limit and the <a href="/routine/open"><code>.open</code></a> call will fail. Note that unlike some other languages, Raku does not use reference counting, so the filehandles <strong>are NOT closed</strong> when the scope they're defined in is left. They will be closed only when they're garbage collected and failing to close the handles may cause your program to reach the file limit <em>before</em> the open handles get a chance to get garbage collected.</p> <h3 id="Reading_from_files" class="raku-h3"><a href="#Input/Output_the_definitive_guide" title="go to top of document">Reading from files<a class="raku-anchor" title="direct link" href="#Reading_from_files">§</a></a></h3> <h4 id="Using_IO::Path" class="raku-h4"><a href="#Input/Output_the_definitive_guide" title="go to top of document">Using IO::Path<a class="raku-anchor" title="direct link" href="#Using_IO::Path">§</a></a></h4> <p>We've seen in previous sections that writing stuff to files is a single-line of code in Raku. Reading from them, is similarly easy:</p> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights"><span class="highlite-ROUTINE">say</span> <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING">my-file.txt</span><span class="highlite-STRING_DELIMITER">'</span>.<span class="highlite-TYPE">IO</span>.<span class="highlite-ROUTINE">slurp</span>; <span class="highlite-COMMENT"># OUTPUT: «I ♥ Raku!␤» </span><span class="highlite-ROUTINE">say</span> <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING">my-file.txt</span><span class="highlite-STRING_DELIMITER">'</span>.<span class="highlite-TYPE">IO</span>.slurp: :bin; <span class="highlite-COMMENT"># OUTPUT: «Buf[uint8]:0x&lt;49 20 E2 99 A5 20 52 61 6B 75 21&gt;␤» </span></pre> </div> </div> <p>The <a href="/routine/slurp"><code>.slurp</code></a> method reads entire contents of the file and returns them as a single <a href="/type/Str"><code>Str</code></a> object, or as a <a href="/type/Buf"><code>Buf</code></a> object, if binary mode was requested, by specifying <code>:bin</code> named argument.</p><p>Since <a href="/routine/slurp">slurping</a> loads the entire file into memory, it's not ideal for working with huge files.</p><p>The <a href="/type/IO/Path"><code>IO::Path</code></a> type offers two other handy methods: <a href="/type/IO/Path#method_words"><code>.words</code></a> and <a href="/type/IO/Path#method_lines"><code>.lines</code></a> that lazily read the file in smaller chunks and return <a href="/type/Seq"><code>Seq</code></a> objects that (by default) don't keep already-consumed values around.</p><p>Here's an example that finds lines in a text file that mention Raku and prints them out. Despite the file itself being too large to fit into available <a href="https://en.wikipedia.org/wiki/Random-access_memory">RAM</a>, the program will not have any issues running, as the contents are processed in small chunks:</p> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights">.<span class="highlite-ROUTINE">say</span> <span class="highlite-KEYWORD">for</span> <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING">500-PetaByte-File.txt</span><span class="highlite-STRING_DELIMITER">'</span>.<span class="highlite-TYPE">IO</span>.<span class="highlite-ROUTINE">lines</span>.grep: <span class="highlite-OPERATOR">*</span>.contains: <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING">Raku</span><span class="highlite-STRING_DELIMITER">'</span>; </pre> </div> </div> <p>Here's another example that prints the first 100 words from a file, without loading it entirely:</p> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights">.<span class="highlite-ROUTINE">say</span> <span class="highlite-KEYWORD">for</span> <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING">500-PetaByte-File.txt</span><span class="highlite-STRING_DELIMITER">'</span>.<span class="highlite-TYPE">IO</span>.words: 100 </pre> </div> </div> <p>Note that we did this by passing a limit argument to <a href="/type/IO/Path#method_words"><code>.words</code></a> instead of, say, using <a href="/language/operators#index-entry-array_indexing_operator-array_subscript_operator-array_indexing_operator">a list indexing operation</a>. The reason for that is there's still a filehandle in use under the hood, and until you fully consume the returned <a href="/type/Seq"><code>Seq</code></a>, the handle will remain open. If nothing references the <a href="/type/Seq"><code>Seq</code></a>, eventually the handle will get closed, during a garbage collection run, but in large programs that work with a lot of files, it's best to ensure all the handles get closed right away. So, you should always ensure the <a href="/type/Seq"><code>Seq</code></a> from <a href="/type/IO/Path"><code>IO::Path</code></a>'s <a href="/type/IO/Path#method_words"><code>.words</code></a> and <a href="/type/IO/Path#method_lines"><code>.lines</code></a> methods is <a href="/language/glossary#Reify">fully reified</a>; and the limit argument is there to help you with that.</p> <h4 id="Using_IO::Handle" class="raku-h4"><a href="#Input/Output_the_definitive_guide" title="go to top of document">Using IO::Handle<a class="raku-anchor" title="direct link" href="#Using_IO::Handle">§</a></a></h4> <p>You can read from files using the <a href="/type/IO/Handle"><code>IO::Handle</code></a> type; this gives you a finer control over the process.</p> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights"><span class="highlite-KEYWORD">given</span> <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING">some-file.txt</span><span class="highlite-STRING_DELIMITER">'</span>.<span class="highlite-TYPE">IO</span>.<span class="highlite-ROUTINE">open</span> { <span class="highlite-ROUTINE">say</span> .readchars: 8; <span class="highlite-COMMENT"># OUTPUT: «I ♥ Raku␤» </span> .seek: 1<span class="highlite-OPERATOR">,</span> SeekFromCurrent; <span class="highlite-ROUTINE">say</span> .readchars: 15; <span class="highlite-COMMENT"># OUTPUT: «I ♥ Programming␤» </span> .<span class="highlite-ROUTINE">close</span> } </pre> </div> </div> <p>The <a href="/type/IO/Handle"><code>IO::Handle</code></a> gives you <a href="/type/IO/Handle#method_read">.read</a>, <a href="/type/IO/Handle#method_readchars">.readchars</a>, <a href="/type/IO/Handle#routine_get">.get</a>, <a href="/type/IO/Handle#routine_getc">.getc</a>, <a href="/type/IO/Handle#routine_words">.words</a>, <a href="/type/IO/Handle#routine_lines">.lines</a>, <a href="/type/IO/Handle#method_slurp">.slurp</a>, <a href="/type/IO/Handle#method_comb">.comb</a>, <a href="/type/IO/Handle#method_split">.split</a>, and <a href="/type/IO/Handle#method_Supply">.Supply</a> methods to read data from it. Plenty of options; and the catch is you need to close the handle when you're done with it.</p><p>Unlike some languages, the handle won't get automatically closed when the scope it's defined in is left. Instead, it'll remain open until it's garbage collected. To make the closing business easier, some of the methods let you specify a <code>:close</code> argument, you can also use the <a href="/language/phasers#index-entry-will_trait"><code>will leave</code> trait</a>, or the <code>does auto-close</code> trait provided by the <a href="https://raku.land/zef:raku-community-modules/Trait::IO"><code>Trait::IO</code></a> module.</p> <h1 id="The_wrong_way_to_do_things" class="raku-h1"><a href="#Input/Output_the_definitive_guide" title="go to top of document">The wrong way to do things<a class="raku-anchor" title="direct link" href="#The_wrong_way_to_do_things">§</a></a></h1> <p>This section describes how NOT to do Raku IO.</p> <h2 id="Leave_$*SPEC_alone" class="raku-h2"><a href="#Input/Output_the_definitive_guide" title="go to top of document">Leave $*SPEC alone<a class="raku-anchor" title="direct link" href="#Leave_$*SPEC_alone">§</a></a></h2> <p>You may have heard of <a href="/language/variables#Dynamic_variables"><code>$*SPEC</code></a> and seen some code or books show its usage for splitting and joining path fragments. Some of the routine names it provides may even look familiar to what you've used in other languages.</p><p>However, unless you're writing your own IO framework, you almost never need to use <a href="/language/variables#Dynamic_variables"><code>$*SPEC</code></a> directly. <a href="/language/variables#Dynamic_variables"><code>$*SPEC</code></a> provides low-level stuff and its use will not only make your code tough to read, you'll likely introduce security issues (e.g. null characters)!</p><p>The <a href="/type/IO/Path"><code>IO::Path</code></a> type is the workhorse of Raku world. It caters to all the path manipulation needs as well as provides shortcut routines that let you avoid dealing with filehandles. Use that instead of the <a href="/language/variables#Dynamic_variables"><code>$*SPEC</code></a> stuff.</p><p>Tip: you can join path parts with <code>/</code> and feed them to <a href="/type/IO/Path"><code>IO::Path</code></a>'s routines; they'll still do The Right Thing™ with them, regardless of the operating system.</p> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights"><span class="highlite-COMMENT"># WRONG!! TOO MUCH WORK! </span><span class="highlite-KEYWORD">my</span> <span class="highlite-NAME_SCALAR">$fh</span> <span class="highlite-OPERATOR">=</span> <span class="highlite-ROUTINE">open</span> <span class="highlite-NAME_SCALAR">$*SPEC</span>.catpath: <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING_DELIMITER">'</span><span class="highlite-OPERATOR">,</span> <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING">foo/bar</span><span class="highlite-STRING_DELIMITER">'</span><span class="highlite-OPERATOR">,</span> <span class="highlite-NAME_SCALAR">$file</span>; <span class="highlite-KEYWORD">my</span> <span class="highlite-NAME_SCALAR">$data</span> <span class="highlite-OPERATOR">=</span> <span class="highlite-NAME_SCALAR">$fh</span>.<span class="highlite-ROUTINE">slurp</span>; <span class="highlite-NAME_SCALAR">$fh</span>.<span class="highlite-ROUTINE">close</span>; </pre> </div> </div> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights"><span class="highlite-COMMENT"># RIGHT! Use IO::Path to do all the dirty work </span><span class="highlite-KEYWORD">my</span> <span class="highlite-NAME_SCALAR">$data</span> <span class="highlite-OPERATOR">=</span> <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING">foo/bar</span><span class="highlite-STRING_DELIMITER">'</span>.<span class="highlite-TYPE">IO</span>.<span class="highlite-ROUTINE">add</span>(<span class="highlite-NAME_SCALAR">$file</span>).<span class="highlite-ROUTINE">slurp</span>; </pre> </div> </div> <p>However, it's fine to use it for things not otherwise provided by <a href="/type/IO/Path"><code>IO::Path</code></a>. For example, the <a href="/routine/devnull"><code>.devnull</code> method</a>:</p> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights">{ <span class="highlite-KEYWORD">temp</span> <span class="highlite-NAME_SCALAR">$*OUT</span> <span class="highlite-OPERATOR">=</span> <span class="highlite-ROUTINE">open</span> :w<span class="highlite-OPERATOR">,</span> <span class="highlite-NAME_SCALAR">$*SPEC</span>.<span class="highlite-ROUTINE">devnull</span>; <span class="highlite-ROUTINE">say</span> <span class="highlite-STRING_DELIMITER">&quot;</span><span class="highlite-STRING">In space no one can hear you scream!</span><span class="highlite-STRING_DELIMITER">&quot;</span>; } <span class="highlite-ROUTINE">say</span> <span class="highlite-STRING_DELIMITER">&quot;</span><span class="highlite-STRING">Hello</span><span class="highlite-STRING_DELIMITER">&quot;</span>; </pre> </div> </div> <h2 id="Stringifying_IO::Path" class="raku-h2"><a href="#Input/Output_the_definitive_guide" title="go to top of document">Stringifying IO::Path<a class="raku-anchor" title="direct link" href="#Stringifying_IO::Path">§</a></a></h2> <p>Don't use the <code>.Str</code> method to stringify <a href="/type/IO/Path"><code>IO::Path</code></a> objects, unless you just want to display them somewhere for information purposes or something. The <code>.Str</code> method returns whatever basic path string the <a href="/type/IO/Path"><code>IO::Path</code></a> was instantiated with. It doesn't consider the value of the <a href="/type/IO/Path#attribute_CWD"><code>$.CWD</code> attribute</a>. For example, this code is broken:</p> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights"><span class="highlite-KEYWORD">my</span> <span class="highlite-NAME_SCALAR">$path</span> <span class="highlite-OPERATOR">=</span> <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING">foo</span><span class="highlite-STRING_DELIMITER">'</span>.<span class="highlite-TYPE">IO</span>; <span class="highlite-ROUTINE">chdir</span> <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING">bar</span><span class="highlite-STRING_DELIMITER">'</span>; <span class="highlite-COMMENT"># WRONG!! .Str DOES NOT USE $.CWD! </span><span class="highlite-ROUTINE">run</span> &lt;tar -cvvf archive.tar&gt;<span class="highlite-OPERATOR">,</span> <span class="highlite-NAME_SCALAR">$path</span>.<span class="highlite-TYPE">Str</span>; </pre> </div> </div> <p>The <a href="/routine/chdir"><code>chdir</code></a> call changed the value of the current directory, but the <code>$path</code> we created is relative to the directory before that change.</p><p>However, the <a href="/type/IO/Path"><code>IO::Path</code></a> object <em>does</em> know what directory it's relative to. We just need to use <a href="/routine/absolute"><code>.absolute</code></a> or <a href="/routine/relative"><code>.relative</code></a> to stringify the object. Both routines return a <a href="/type/Str"><code>Str</code></a> object; they only differ in whether the result is an absolute or relative path. So, we can fix our code like this:</p> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights"><span class="highlite-KEYWORD">my</span> <span class="highlite-NAME_SCALAR">$path</span> <span class="highlite-OPERATOR">=</span> <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING">foo</span><span class="highlite-STRING_DELIMITER">'</span>.<span class="highlite-TYPE">IO</span>; <span class="highlite-ROUTINE">chdir</span> <span class="highlite-STRING_DELIMITER">'</span><span class="highlite-STRING">bar</span><span class="highlite-STRING_DELIMITER">'</span>; <span class="highlite-COMMENT"># RIGHT!! .absolute does consider the value of $.CWD! </span><span class="highlite-ROUTINE">run</span> &lt;tar -cvvf archive.tar&gt;<span class="highlite-OPERATOR">,</span> <span class="highlite-NAME_SCALAR">$path</span>.<span class="highlite-ROUTINE">absolute</span>; <span class="highlite-COMMENT"># Also good: </span><span class="highlite-ROUTINE">run</span> &lt;tar -cvvf archive.tar&gt;<span class="highlite-OPERATOR">,</span> <span class="highlite-NAME_SCALAR">$path</span>.<span class="highlite-ROUTINE">relative</span>; </pre> </div> </div> <h2 id="Be_mindful_of_$*CWD" class="raku-h2"><a href="#Input/Output_the_definitive_guide" title="go to top of document">Be mindful of $*CWD<a class="raku-anchor" title="direct link" href="#Be_mindful_of_$*CWD">§</a></a></h2> <p>While usually out of view, every <a href="/type/IO/Path"><code>IO::Path</code></a> object, by default, uses the current value of <a href="/language/variables#Dynamic_variables"><code>$*CWD</code></a> to set its <a href="/type/IO/Path#attribute_CWD"><code>$.CWD</code> attribute</a>. This means there are two things to pay attention to.</p> <h3 id="temp_the_$*CWD" class="raku-h3"><a href="#Input/Output_the_definitive_guide" title="go to top of document">temp the $*CWD<a class="raku-anchor" title="direct link" href="#temp_the_$*CWD">§</a></a></h3> <p>This code is a mistake:</p> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights"><span class="highlite-COMMENT"># WRONG!! </span><span class="highlite-KEYWORD">my</span> <span class="highlite-NAME_SCALAR">$*CWD</span> <span class="highlite-OPERATOR">=</span> <span class="highlite-STRING_DELIMITER">&quot;</span><span class="highlite-STRING">foo</span><span class="highlite-STRING_DELIMITER">&quot;</span>.<span class="highlite-TYPE">IO</span>; </pre> </div> </div> <p>The <code>my $*CWD</code> made <a href="/language/variables#Dynamic_variables"><code>$*CWD</code></a> undefined. The <a href="/routine/IO"><code>.IO</code></a> coercer then goes ahead and sets the <a href="/type/IO/Path#attribute_CWD"><code>$.CWD</code> attribute</a> of the path it's creating to the stringified version of the undefined <code>$*CWD</code>; an empty string.</p><p>The correct way to perform this operation is use <a href="/routine/temp"><code>temp</code></a> instead of <code>my</code>. It'll localize the effect of changes to <a href="/language/variables#Dynamic_variables"><code>$*CWD</code></a>, just like <code>my</code> would, but it won't make it undefined, so the <a href="/routine/IO"><code>.IO</code></a> coercer will still get the correct old value:</p> <div class="raku-code raku-lang"> <button class="copy-code" title="Copy code"><i class="far fa-clipboard"></i></button> <label>Raku highlighting</label> <div> <pre class="nohighlights"><span class="highlite-KEYWORD">temp</span> <span class="highlite-NAME_SCALAR">$*CWD</span> <span class="highlite-OPERATOR">=</span> <span class="highlite-STRING_DELIMITER">&quot;</span><span class="highlite-STRING">foo</span><span class="highlite-STRING_DELIMITER">&quot;</span>.<span class="highlite-TYPE">IO</span>; </pre> </div> </div> <p>Better yet, if you want to perform some code in a localized <a href="/language/variables#Dynamic_variables"><code>$*CWD</code></a>, use the <a href="/routine/indir"><code>indir</code> routine</a> for that purpose.</p> </div></div></section> </div> </div> </div> <footer class="footer main-footer"> <div class="container px-4"> <nav class="level"> <div class="level-left"> <div class="level-item"> <a href="/about">About</a> </div> <div class="level-item"> <a id="toggle-theme">Toggle theme</a> </div> <div class="level-item" title="2da8bda47 2024-07-23"> <a>Commit</a> </div> </div> <div class="level-right"> <div class="level-item"> <a href="/license">License</a> </div> </div> </nav> </div> </footer> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10