title: How to read a file character by character in Go
body: <p>I have some large json files I want to parse, and I want to avoid loading all of the data into memory at once.  I'd like a function/loop that can return me each character one at a time.</p>
  
  <p>I found <a href="http://golangcookbook.com/chapters/strings/processing/" rel="noreferrer">this example</a> for iterating over words in a string, and <a href="http://golang.org/pkg/bufio/#ScanRunes" rel="noreferrer">the ScanRunes</a> function in the bufio package looks like it could return a character at a time.  I also had the <code>ReadRune</code> function from bufio mostly working, but that felt like a pretty heavy approach.</p>
  
  <h2>EDIT</h2>
  
  <p>I compared 3 approaches.  All used a loop to pull content from either a bufio.Reader or a bufio.Scanner.</p>
  
  <ol>
  <li>Read runes in a loop using <code>.ReadRune</code> on a <code>bufio.Reader</code>. Checked for errors from the call to <code>.ReadRune</code>.</li>
  <li>Read bytes from a <code>bufio.Scanner</code> after calling <code>.Split(bufio.ScanRunes)</code> on the scanner. Called <code>.Scan</code> and <a href="http://golang.org/pkg/bufio/#Scanner.Bytes" rel="noreferrer"><code>.Bytes</code></a> on each iteration, checking <code>.Scan</code> call for errors.</li>
  <li>Same as #2 but read text from a <code>bufio.Scanner</code> instead of bytes using <a href="http://golang.org/pkg/bufio/#Scanner.Text" rel="noreferrer"><code>.Text</code></a>.  Instead of joining a slice of runes with <code>string([]runes)</code>, I joined an slice of strings with <code>strings.Join([]strings, "")</code> to form the final blobs of text.</li>
  </ol>
  
  <p>The timing for 10 runs of each on a 23 MB json file was:</p>
  
  <ol>
  <li><code>0.65 s</code></li>
  <li><code>2.40 s</code></li>
  <li><code>0.97 s</code></li>
  </ol>
  
  <p>So it looks like <code>ReadRune</code> is not too bad after all.  It also results in smaller less verbose call because each rune is fetched in 1 operation (<code>.ReadRune</code>) instead of 2 (<code>.Scan</code> and <code>.Bytes</code>).</p>