


Abaikan baris yang mengandungi corak dalam fail teks panjang dalam Go
php Editor Apple Dalam bahasa Go, kita selalunya perlu memproses fail teks yang besar. Kadangkala kami hanya berminat dengan baris yang mengandungi corak tertentu dan mengabaikan baris lain. Nasib baik, dalam Go, kita boleh menggunakan ungkapan biasa dan bufio.Scanner untuk mencapai matlamat ini. Dengan menggunakan ungkapan biasa untuk memadankan baris dan menjalankan fail melalui Pengimbas baris demi baris, kami boleh menapis dengan mudah baris yang kami tidak minati. Petua ini bukan sahaja meningkatkan kecekapan, tetapi juga menjadikan kod kami lebih ringkas dan boleh dibaca. Seterusnya, mari kita lihat cara mengabaikan baris yang mengandungi corak dalam fail teks panjang dalam Go.
Kandungan soalan
Saya cuba melaksanakan fungsi untuk mengabaikan baris yang mengandungi corak dalam fail teks panjang (aci terjamin) dalam perjalanan
Saya withoutignore
和 withignore
下面的函数都接受文件名参数输入并返回 *byte.buffer
,随后可用于写入 io.writer
.
withignore
函数采用附加参数 pattern
从文件中排除包含模式的行。该函数可以工作,但通过基准测试,发现它比 慢 5 倍而不忽略
. Adakah terdapat apa-apa cara ia boleh diperbaiki?
package main import ( "bufio" "bytes" "io" "log" "os" ) func withoutignore(f string) (*bytes.buffer, error) { rfd, err := os.open(f) if err != nil { log.fatal(err) } defer func() { if err := rfd.close(); err != nil { log.fatal(err) } }() inputbuffer := make([]byte, 1048576) var bytesread int var bs []byte opbuffer := bytes.newbuffer(bs) for { bytesread, err = rfd.read(inputbuffer) if err == io.eof { return opbuffer, nil } if err != nil { return nil, nil } _, err = opbuffer.write(inputbuffer[:bytesread]) if err != nil { return nil, err } } return opbuffer, nil } func withignore(f, pattern string) (*bytes.buffer, error) { rfd, err := os.open(f) if err != nil { log.fatal(err) } defer func() { if err := rfd.close(); err != nil { log.fatal(err) } }() scanner := bufio.newscanner(rfd) var bs []byte buffer := bytes.newbuffer(bs) for scanner.scan() { if !bytes.contains(scanner.bytes(), []byte(pattern)) { _, err := buffer.writestring(scanner.text() + "\n") if err != nil { return nil, nil } } } return buffer, nil } func main() { // buff, err := withoutignore("base64dump.log") buff, err := withignore("base64dump.log", "audit") if err != nil { log.fatal(err) } _, err = buff.writeto(os.stdout) if err != nil { log.fatal(err) } }
Tanda aras
package main import "testing" func benchmarktestwithoutignore(b *testing.b) { for i := 0; i < b.n; i++ { _, err := withoutignore("base64dump.log") if err != nil { b.fatal(err) } } } func benchmarktestwithignore(b *testing.b) { for i := 0; i < b.n; i++ { _, err := withignore("base64dump.log", "audit") if err != nil { b.fatal(err) } } }
Dan boleh digunakan dari baris arahan“base64dump.log”生成
base64 /dev/urandom | head -c 10000000 > base64dump.log
Penyelesaian
Oleh kerana ascii dijamin, ia boleh berfungsi secara langsung pada tahap byte
.
Walau bagaimanapun, jika anda menyemak setiap bait untuk aksara baris baharu semasa membaca input, dan kemudian mencari dalam baris itu sekali lagi untuk corak, operasi akan digunakan pada setiap bait.
Sebaliknya, jika anda membaca blok input dan melakukan carian yang dioptimumkan untuk corak dalam teks, tanpa menyemak setiap bait input, anda boleh meminimumkan operasi setiap bait input.
Sebagai contoh, algoritma carian rentetan boyer-moore. Fungsi bytes.index
terbina dalam Go juga telah dioptimumkan. Kelajuan yang dicapai sudah tentu bergantung pada data input dan mod sebenar. Untuk input yang dinyatakan dalam soalan, prestasi `bytes.index meningkat dengan ketara apabila diukur.
Program
- Membaca blok di mana saiz blok harus jauh lebih panjang daripada panjang garis maksimum, nilai >= 64kb mungkin bagus, dalam ujian saya menggunakan 1mb dalam soalan.
- Sebuah blok biasanya tidak berakhir dengan baris baharu, jadi cari dari hujung blok ke baris baharu seterusnya, hadkan carian kepada kepingan ini dan ingat baki data untuk laluan seterusnya
- Blok terakhir tidak semestinya berakhir dengan watak baris baharu
- Dengan bantuan fungsi go berprestasi tinggi
bytes.index
anda boleh mencari di mana dalam blok corak itu berlaku - Cari aksara baris baharu sebelum dan seterusnya dari kedudukan ditemui
- Blok kemudian dikeluarkan ke permulaan baris yang sepadan
- Dan teruskan mencari dari hujung baris di mana corak muncul
- Jika carian tidak menemui lokasi lain, keluarkan lokasi yang tinggal
- Baca bahagian seterusnya dan gunakan langkah yang diterangkan sekali lagi sehingga anda sampai ke penghujung fail
Perhatian
Operasi baca mungkin mengembalikan data yang kurang daripada saiz blok, jadi masuk akal untuk mengulang operasi baca sehingga saiz blok data dibaca.
Tanda aras
Kod yang dioptimumkan biasanya jauh lebih kompleks, tetapi juga menunjukkan prestasi yang lebih baik, seperti yang akan kita lihat nanti.
benchmarktestwithoutignore-8 270 4137267 ns/op benchmarktestwithignore-8 54 22403931 ns/op benchmarktestfilter-8 150 7947454 ns/op
Di sini, kaedah benchmarktestfilter-8
只比没有过滤的操作慢1.9倍左右,而benchmarktestwithignore-8
kod yang dioptimumkan adalah 5.4 kali lebih perlahan daripada nilai perbandingan yang tidak ditapis.
Lihat dari perspektif lain: kod yang dioptimumkan adalah 2.8 kali lebih pantas daripada kod yang tidak dioptimumkan.
kod
Sudah tentu, berikut ialah kod untuk ujian anda sendiri:
func filterfile(f, pattern string) (*bytes.buffer, error) { rfd, err := os.open(f) if err != nil { log.fatal(err) } defer func() { if err := rfd.close(); err != nil { log.fatal(err) } }() reader := bufio.newreader(rfd) return filter(reader, []byte(pattern), 1024*1024) } // chunksize must be larger than the longest line // a reasonable size is probably >= 64k func filter(reader io.reader, pattern []byte, chunksize int) (*bytes.buffer, error) { var bs []byte buffer := bytes.newbuffer(bs) chunk := make([]byte, chunksize) var remaining []byte for lastchunk := false; !lastchunk; { n, err := readchunk(reader, chunk, remaining, chunksize) if err != nil { if err == io.eof { lastchunk = true } else { return nil, err } } remaining = remaining[:0] if !lastchunk { for i := n - 1; i > 0; i-- { if chunk[i] == '\n' { remaining = append(remaining, chunk[i+1:n]...) n = i + 1 break } } } s := 0 for s < n { hit := bytes.index(chunk[s:n], pattern) if hit < 0 { break } hit += s startofline := hit for ; startofline > 0; startofline-- { if chunk[startofline] == '\n' { startofline++ break } } endofline := hit + len(pattern) for ; endofline < n; endofline++ { if chunk[endofline] == '\n' { break } } endofline++ _, err = buffer.write(chunk[s:startofline]) if err != nil { return nil, err } s = endofline } if s < n { _, err = buffer.write(chunk[s:n]) if err != nil { return nil, err } } } return buffer, nil } func readchunk(reader io.reader, chunk, remaining []byte, chunksize int) (int, error) { copy(chunk, remaining) r := len(remaining) for r < chunksize { n, err := reader.read(chunk[r:]) r += n if err != nil { return r, err } } return r, nil }
Bahagian penanda aras mungkin kelihatan seperti ini:
func BenchmarkTestFilter(b *testing.B) { for i := 0; i < b.N; i++ { _, err := filterFile("base64dump.log", "AUDIT") if err != nil { b.Fatal(err) } } }
Fungsi penapis berpecah dan kerja sebenar dilakukan dalam func filter(reader io.reader,pattern []byte, chunksize int) (*bytes.buffer, error)
.
Penciptaan ujian unit telah disediakan atau diambil kira dengan menyuntik pembaca dan chunksize, yang tiada di sini tetapi pasti disyorkan apabila berurusan dengan indeks.
Walau bagaimanapun, perkara di sini adalah untuk mencari cara untuk meningkatkan prestasi dengan ketara.
Atas ialah kandungan terperinci Abaikan baris yang mengandungi corak dalam fail teks panjang dalam Go. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Masalah Threading Giliran di GO Crawler Colly meneroka masalah menggunakan Perpustakaan Colly Crawler dalam bahasa Go, pemaju sering menghadapi masalah dengan benang dan permintaan beratur. � ...

Perpustakaan yang digunakan untuk operasi nombor terapung dalam bahasa Go memperkenalkan cara memastikan ketepatannya ...

Masalah menggunakan redisstream untuk melaksanakan beratur mesej dalam bahasa Go menggunakan bahasa Go dan redis ...

Perbezaan antara percetakan rentetan dalam bahasa Go: perbezaan kesan menggunakan fungsi println dan rentetan () sedang ...

Apa yang perlu saya lakukan jika label struktur tersuai di Goland tidak dipaparkan? Apabila menggunakan Goland untuk Pembangunan Bahasa GO, banyak pemaju akan menghadapi tag struktur tersuai ...

Dua cara untuk menentukan struktur dalam bahasa Go: perbezaan antara VAR dan jenis kata kunci. Apabila menentukan struktur, pergi bahasa sering melihat dua cara menulis yang berbeza: pertama ...

Perpustakaan mana yang dibangunkan oleh syarikat besar atau projek sumber terbuka yang terkenal? Semasa pengaturcaraan di GO, pemaju sering menghadapi beberapa keperluan biasa, ...

GO Pointer Syntax dan menangani masalah dalam penggunaan perpustakaan Viper semasa pengaturcaraan dalam bahasa Go, adalah penting untuk memahami sintaks dan penggunaan petunjuk, terutama dalam ...
