質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

Q&A

解決済

2回答

4750閲覧

[Go(golang)] ファイル末尾から1行ずつ読み込みたい

退会済みユーザー

退会済みユーザー

総合スコア0

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

0グッド

1クリップ

投稿2018/05/26 00:21

Go言語でログファイルなど、ファイル末尾から1行読み込んで順次処理を行いたいのですが、これは自前で実装するしかないのでしょうか?

もし簡単な方法がありましたら教えて下さい。宜しくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

このようなことを昔やろうとしていたのですが、OSSにしていなかったので先程OSSにしておきました。
https://github.com/pyama86/ptail

投稿2018/05/28 07:15

pyama86

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/05/29 08:13

おお、便利そうだ!回答ありがとうございます。
guest

0

ベストアンサー

単純に行単位で読み切って逆順で表示するだけです。

go

1package main 2 3import ( 4 "bufio" 5 "fmt" 6 "log" 7 "os" 8) 9 10func main() { 11 fp, err := os.Open("log.txt") 12 if err != nil { 13 log.Fatalln(err) 14 } 15 defer fp.Close() 16 scanner := bufio.NewScanner(fp) 17 lines := []string{} 18 for scanner.Scan() { 19 lines = append(lines, scanner.Text()) 20 } 21 for i := range lines { 22 fmt.Println(lines[len(lines)-i-1]) 23 } 24}

ただこれを巨大なログファイルなどに適用するとメモリが大変なことになります。

  • fp.Stat()でえられるファイルサイズ分
  • io.Seekableなfp.Seekでシークしながら
  • ファイルを読みつつ改行を探す

go

1package main 2 3import ( 4 "fmt" 5 "io" 6 "log" 7 "os" 8) 9 10func main() { 11 fp, err := os.Open("log.txt") 12 if err != nil { 13 log.Fatalln(err) 14 } 15 defer fp.Close() 16 info, err := fp.Stat() 17 if err != nil { 18 log.Fatalln(err) 19 } 20 pos := info.Size() 21 line := "" 22 for pos > 0 { 23 b := []byte{0} 24 _, err := fp.Seek(pos-1, os.SEEK_SET) 25 if err != nil { 26 log.Fatalln(err) 27 } 28 sz, err := fp.Read(b) 29 if err != nil { 30 if err != io.EOF { 31 log.Fatalln(err) 32 } 33 } 34 if sz > 0 { 35 if b[0] == '\n' { 36 if len(line) > 0 { 37 fmt.Println(line) 38 line = "" 39 } 40 } else { 41 line = string(b) + line 42 } 43 pos-- 44 } 45 } 46 if len(line) > 0 { 47 fmt.Println(line) 48 } 49}

しかし、この方法もシステムコールの発行回数が多く、
巨大なファイルの場合に効率がよくありません。
チャンク(かたまり)サイズ毎に逆順に読んで、
チャンクごとにうまく改行単位の切り出しをすると良いでしょう。
参考実装はtacというLinuxのコマンドラインツールを参考に。
(もしくはtacコマンドを子プロセスとして呼ぶ手もあります)

投稿2018/05/27 21:41

nobonobo

総合スコア3367

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nobonobo

2018/05/28 00:49

ちなみにtacは8KBセグメントを1チャンクとして扱うみたい。
退会済みユーザー

退会済みユーザー

2018/05/29 08:11

思ったより結構手間がかかるものなんですね。 回答有り難うございます。参考にさせて頂きます。
nobonobo

2018/05/29 23:18

システム(OS)が、順読みしか支援してくれないので、、、。この課題はどの言語でもややこしくなります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問