golangファイルを行単位で処理
4441 ワード
golangはpackage bufioを提供しています.bufio.NewReader()はデフォルトサイズのreadbufを作成します.もちろんbufioもできます.NewReaderSize.
bufio
ReadByteというインタフェースは、C言語のfgetcに近く、1バイトずつ読み込まれます.ReadBytesとReadStringはdelimが'′に設定限り、行ごとの読み取りを実現することができる.
scanerで行単位で読み込む
なぜScanを実行すると、Text()関数は次の行に戻るのでしょうか.デフォルトの分割関数はScanLinesだからです.分割に特別なニーズがある場合は、func(s*Scanner)Split(split SplitFunc)
この関数はSplitFuncを作成することができます.独自の分割関数をカスタマイズできます.
なお、Scanは分割記号を削除し、Fprintfが出力されると、印刷を追加しないで改行しない現象が発生します.以下のようになります
呼び出し部分のコードは次のとおりです.
func NewReader(rd io.Reader) *Reader
NewReader returns a new Reader whose buffer has the default size(4096).
func NewReaderSize(rd io.Reader, size int) *Reader
NewReaderSize returns a new Reader whose buffer has at least the
specified size. If the argument io.Reader is already a Reader with large
enough size, it returns the underlying Reader.
bufio
func (b *Reader) ReadByte() (c byte, err error)
ReadByte reads and returns a single byte. If no byte is available,
returns an error.
func (b *Reader) ReadBytes(delim byte) (line []byte, err error)
ReadBytes reads until the first occurrence of delim in the input,
returning a slice containing the data up to and including the delimiter.
If ReadBytes encounters an error before finding a delimiter, it returns
the data read before the error and the error itself (often io.EOF).
ReadBytes returns err != nil if and only if the returned data does not
end in delim. For simple uses, a Scanner may be more convenient.
func (b *Reader) ReadString(delim byte) (line string, err error)
ReadString reads until the first occurrence of delim in the input,
returning a string containing the data up to and including the
delimiter. If ReadString encounters an error before finding a delimiter,
it returns the data read before the error and the error itself (often
io.EOF). ReadString returns err != nil if and only if the returned data
does not end in delim. For simple uses, a Scanner may be more
convenient.
ReadByteというインタフェースは、C言語のfgetcに近く、1バイトずつ読み込まれます.ReadBytesとReadStringはdelimが'′に設定限り、行ごとの読み取りを実現することができる.
package main
import "fmt"
import "os"
import "io"
import "flag"
import "bufio"
var num_flag = flag.Bool("n",false,"num each line")
func usage(){
fmt.Printf("%s %s
",os.Args[0],"filename")
}
func cat(r *bufio.Reader){
i := 1
for {
//buf,err := r.ReadBytes('
')
buf,err := r.ReadString('
')
if err == io.EOF{
break
}
if *num_flag{
fmt.Fprintf(os.Stdout,"%5d %s",
i,buf)
i++
}else{
fmt.Fprintf(os.Stdout,"%s",buf)
}
}
return
}
func main(){
flag.Parse()
if(flag.NArg() == 0){
cat(bufio.NewReader(os.Stdin))
}
for i:=0;i<flag.NArg();i++{
f,err := os.OpenFile(flag.Arg(i),os.O_RDONLY,0660)
if err != nil{
fmt.Fprintf(os.Stderr,"%s err read from %s : %s
",
os.Args[0],flag.Arg(0),err)
continue
}
cat(bufio.NewReader(f))
f.Close()
}
}
scanerで行単位で読み込む
func cat(scanner *bufio.Scanner) error{
for scanner.Scan(){
fmt.Println(scanner.Text())
//fmt.Fprintf(os.Stdout,"%s
",scanner.Text())
}
return scanner.Err()
}
なぜScanを実行すると、Text()関数は次の行に戻るのでしょうか.デフォルトの分割関数はScanLinesだからです.分割に特別なニーズがある場合は、func(s*Scanner)Split(split SplitFunc)
この関数はSplitFuncを作成することができます.独自の分割関数をカスタマイズできます.
なお、Scanは分割記号を削除し、Fprintfが出力されると、印刷を追加しないで改行しない現象が発生します.以下のようになります
fmt.Fprintf(os.Stdout,"%s",scanner.Text())
manu@manu-hacks:~/code/go/self$ go run mycat_v2.go test.txt
this is test file created by goif not existed ,please create this fileif existed, Please write appendhello world,hello gothis is test file created by goif not existed ,please create this fileif existed, Please write appendhello world,hello gomanu@manu-hacks:~/code/go/self$ cat test.txt
this is test file created by go
if not existed ,please create this file
if existed, Please write append
hello world,hello go
this is test file created by go
if not existed ,please create this file
if existed, Please write append
hello world,hello go
呼び出し部分のコードは次のとおりです.
f,err := os.OpenFile(flag.Arg(i),os.O_RDONLY,0660)
...
error := cat(bufio.NewScanner(f))
if err != nil{
fmt.Fprintf(os.Stderr,"%s err read from %s : %s
",
os.Args[0],flag.Arg(i),error)
}