<p>Hi, guys! A fairly newb gopher here. What I'm trying to do is get a text file (w/ Lorem Ipsum) text, read it into a slice, then print the whole contents of the file out. </p>
<p>However, it is my understanding, that for large files it's inefficient to dump the whole thing into the memory (and also there are limitations on how much reading can be done at a time. So, my solution is to implement a transfer slice (data, []byte) which will iterate over the file and append itself into a finalFile ([]byte) slice that will contain the full text.</p>
<p>So, here it is!</p>
<p><code>func main() {</code><br/>
<code>f, err := os.Open("text.txt")</code><br/>
<code>defer f.Close()</code><br/>
<code>if err != nil {</code><br/>
<code>fmt.Println("Issue opening the file")</code><br/>
<code>}</code><br/>
<code>data := make([]byte, 100) // initializing a transfer slice that will read the text.txt 100 bytes at a time</code><br/>
<code>fullFile := []byte{} // initializing the final destination slice</code><br/>
<code>var count int // declaring the file byte length variable</code><br/>
<code>for n, err := f.Read(data); err == nil; { //reading n bytes (up to 100) into the transfer slice and checking for error (EOF) condition</code><br/>
<code>fullFile = append(fullFile, data...) // appending to the final destination slice</code><br/>
<code>count = count + n // tickign up the counter of read bytes</code><br/>
<code>n, err = f.Read(data) //reading into the final destination file again and updating the error variable. If this line is missing >> inf. loop</code><br/>
<code>} // if n is _, the tail-end of the previous transfer slice is printed.</code><br/>
<code>fmt.Printf("read %d bytes: %q\n", count, fullFile[:count]) // if fullFile[:], the tail-end of the previous tranfer slice is printed</code></p>
<p><code>}</code></p>
<p>So, the code works perfectly the way it's written. However, I don't know why! Specifically:</p>
<ol>
<li>Why do I need to have "n, err = <a href="https://f.Read">f.Read</a>(data)"? Why doesn't both reading and error condition checking not happening in the for loop argument line where (i thought) it was supposed to be happening?</li>
<li>So, I realized that "err" in the loop arguments line wasn't updating sending the program into an infinite loop. Then added "n, err = <a href="https://f.Read">f.Read</a>(data)" mostly to introduce a way to update the err value to break out of the loop. But that introduced another bug. If I don't have "n", and have "_, err = <a href="https://f.Read">f.Read</a>(data)", the un-overwritten portion of the transfer slice (data) from the previous read gets appended to the final slice. (This happens whether I set the "fullFile[:count]" or "fullFile[:]). What gives? Why does it happen?</li>
<li>Leaving the "n" from 2 in, ff I remove "fullFile[:count]" and use "fullFile[:]" instead, same effect happens . I understand that what I do is essentially truncating the output slice to print only the number of bytes that were read from the original file. But can the writing of old bytes from the "data" slice be avoided altogether?</li>
</ol>
<p>This is the content of my text file and the output when the program works properly:</p>
<p><code>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</code></p>
<p>This is the buggy output:</p>
<p><code>read 445 bytes: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.sint occaecat cupidatat non proident, sunt in culpa qui"</code></p>
<p>See how there're extra 55 bytes at the end after "laborum." on the last line? "<code>sint occaecat cupidatat non proident, sunt in culpa qui"</code> was clearly a leftover from the iteration of <a href="https://f.Read">f.Read</a>(data) before the final read.</p>
<p>Thank you SO much for looking at this if you did! </p>
<hr/>**评论:**<br/><br/>unix15e8: <pre><p>You could do this instead:</p>
<pre><code>for {
n, err := f.Read(data)
if err != nil {
fmt.Println("read.fail;", err)
break
}
fullFile = append(fullFile, data...)
count = count + n
}
</code></pre>
<p>A better way to solve this is to use the <a href="https://golang.org/pkg/bufio/" rel="nofollow">bufio</a> package, <a href="https://play.golang.org/p/E9SGUYKtZNP" rel="nofollow">like this</a>.</p></pre>ODAwake: <pre><p>omg! I forgot about 'break'! Instead of packing everything into the loop argument lines I could've avoided that completely! Thank you!</p>
<p>The reason I didn't want to use bufio's scanner was to just get more comfortable with the Read/Write functions. (I'm just starting on the Read() ). And also to get a better handle on slicing and appending and such. I'm still fairly new with the language. This is essentially the first programming language that I got to study on my own in the last two decades. Had some C++ back in college, but that was SO long ago!</p></pre>unix15e8: <pre><p>You can also break if the reader has reached the end of the file:</p>
<pre><code>for {
n, err := f.Read(data)
if err == io.EOF {
/* graceful stop */
break
}
if err != nil {
/* unexpected reader failure */
fmt.Println("read.fail;", err)
break
}
…
}
</code></pre></pre>ODAwake: <pre><p>Hah! I was just implementing that!!! </p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传