示例代码是,
// test.go
package main
import (
"bufio"
"os"
)
func main() {
if len(os.Args) != 2 {
println("Usage:", os.Args[0], "")
os.Exit(1)
}
fileName := os.Args[1]
fp, err := os.Open(fileName)
if err != nil {
println(err.Error())
os.Exit(2)
}
defer fp.Close()
r := bufio.NewScanner(fp)
var lines []string
for r.Scan() {
lines = append(lines, r.Text())
}
}
c:\> go build test.go
c:\> test.exe test.txt
然后我在执行时使用进程监视器监视其进程,部分输出是:
test.exe ReadFile SUCCESS Offset: 4,692,375, Length: 8,056
test.exe ReadFile SUCCESS Offset: 4,700,431, Length: 7,198
test.exe ReadFile SUCCESS Offset: 4,707,629, Length: 8,134
test.exe ReadFile SUCCESS Offset: 4,715,763, Length: 7,361
test.exe ReadFile SUCCESS Offset: 4,723,124, Length: 8,056
test.exe ReadFile SUCCESS Offset: 4,731,180, Length: 4,322
test.exe ReadFile END OF FILE Offset: 4,735,502, Length: 8,192
等效的java代码是,
//Test.java
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
public class Test{
public static void main(String[] args) {
try
{
FileInputStream in = new FileInputStream("test.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
while((strLine = br.readLine())!= null)
{
;
}
}catch(Exception e){
System.out.println(e);
}
}
}
c:\> javac Test.java
c:\> java Test
然后部分监控输出是:
java.exe ReadFile SUCCESS Offset: 4,694,016, Length: 8,192
java.exe ReadFile SUCCESS Offset: 4,702,208, Length: 8,192
java.exe ReadFile SUCCESS Offset: 4,710,400, Length: 8,192
java.exe ReadFile SUCCESS Offset: 4,718,592, Length: 8,192
java.exe ReadFile SUCCESS Offset: 4,726,784, Length: 8,192
java.exe ReadFile SUCCESS Offset: 4,734,976, Length: 526
java.exe ReadFile END OF FILE Offset: 4,735,502, Length: 8,192
如您所见,java中的缓冲区大小为8192,每次读取8192个字节。为什么每次读取文件时,Go in Go都会发生变化?
我尝试了bufio.ReadString('\n')
,bufio.ReadBytes('\n')
,但他们都遇到了同样的问题。
[更新] 我用C测试了样本,
//test.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE * fp;
char * line = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("test.txt", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1) {
printf("Retrieved line of length %zu :\n", read);
}
if (line)
free(line);
return EXIT_SUCCESS;
}
输出类似于java代码(我的系统上缓冲区大小为65536)。那么为什么Go在这里有如此不同?
答案 0 :(得分:2)
阅读bufio.Scan
&#39; source显示,当缓冲区大小为4096时,它会根据多少&#34;空&#34;空间留在其中,特别是这部分:
n, err := s.r.Read(s.buf[s.end:len(s.buf)])
现在性能明智,我几乎肯定你所使用的任何文件系统都足够聪明,可以预读和缓存数据,因此缓冲区大小不应该大大增加差。
答案 1 :(得分:1)
这可能是的原因:
在您引用的所有示例中,Scan
函数输出由行结尾确定。
Go的默认扫描功能按行分割(http://golang.org/pkg/bufio/#Scanner.Scan):
默认的拆分功能将输入分为线路终端剥离的行
由于bufio.ReadString('\n')
字符,bufio.ReadBytes('\n')
和\n
存在同样的问题。
尝试从测试文件中删除所有换行符并测试它是否仍在READFILE
条记录中提供非4096倍。
正如一些人所建议的,你所看到的实际上可能是由于bufio
包使用的IO策略。