Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 85 additions & 1 deletion hw07_file_copying/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,98 @@ package main

import (
"errors"
"io"
"os"

"github.com/cheggaaa/pb/v3"
)

var (
ErrFileNotExist = errors.New("file doesn't exist")
ErrUnsupportedFile = errors.New("unsupported file")
ErrOffsetExceedsFileSize = errors.New("offset exceeds file size")
)

func Copy(fromPath string, toPath string, offset, limit int64) error {
// Place your code here
err := fileErrors(fromPath, offset)
if err != nil {
return err
}

// use limited reader instead default reader
limit = changeZeroLimit(fromPath, limit)
limitedReader, err := openLimitedReader(fromPath, offset, limit)
if err != nil {
return err
}

// define bar reader
bar := pb.Full.Start64(limit)
defer bar.Finish()
barReader := bar.NewProxyReader(limitedReader)
defer barReader.Close()

// define default writer
writer, err := os.Create(toPath)
if err != nil {
return err
}
defer writer.Close()

_, err = io.Copy(writer, barReader)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лучше воспользоваться io.CopyN().

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тогда нужно будет цикл делать?
Я ведь правильно понял, что цель — копировать небольшими «порциями»?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Он внутри копирует порциями.

if err != nil {
return err
}

return nil
}

func fileErrors(fromPath string, offset int64) error {
fileSt, err := os.Stat(fromPath)
if os.IsNotExist(err) {
return ErrFileNotExist
}
// check other errors
if err != nil {
return err
}

fileSize := fileSt.Size()
if fileSize < 0 {
return ErrUnsupportedFile
}
if offset > fileSize {
return ErrOffsetExceedsFileSize
}

return nil
}

func changeZeroLimit(fromPath string, limit int64) int64 {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А может ли быть вариант, когда offset + limit > fileSize ? Что тогда делать?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Внутри openLimitedReader есть проверка на offset, а limit не может быть больше FileSize.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

limit задаётся как внешний параметр, его можно задать и больше чем FileSize, не вижу где в работе проверяется это ограничение.

fileSt, err := os.Stat(fromPath)
// stay limit unchanged if stat caught error
if err != nil {
return limit
}

if limit < 1 {
limit = fileSt.Size()
}

return limit
}

func openLimitedReader(fromPath string, offset, limit int64) (io.Reader, error) {
reader, err := os.Open(fromPath)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Файлы надо закрывать.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Закрываю в main сам reader.

if err != nil {
return reader, err
}

_, err = reader.Seek(offset, io.SeekStart)
if err != nil {
return reader, err
}
limitedReader := io.LimitReader(reader, limit)

return limitedReader, nil
}
17 changes: 15 additions & 2 deletions hw07_file_copying/copy_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
package main

import "testing"
import (
"math"
"testing"

"github.com/stretchr/testify/require"
)

func TestCopy(t *testing.T) {
// Place your code here
t.Run("Check not exists file", func(t *testing.T) {
err := Copy("not-exist-file", "", 0, 0)
require.Equal(t, err, ErrFileNotExist)
})

t.Run("Too long offset", func(t *testing.T) {
err := Copy("testdata/input.txt", "", int64(math.Exp2(20)), 0)
require.Equal(t, err, ErrOffsetExceedsFileSize)
})
}
7 changes: 6 additions & 1 deletion hw07_file_copying/go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
module github.com/fixme_my_friend/hw07_file_copying
module github.com/ezhk/golang-learning/hw07_file_copying

go 1.14

require (
github.com/cheggaaa/pb/v3 v3.0.4
github.com/stretchr/testify v1.6.1
)
28 changes: 28 additions & 0 deletions hw07_file_copying/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
github.com/cheggaaa/pb v1.0.28 h1:kWGpdAcSp3MxMU9CCHOwz/8V0kCHN4+9yQm2MzWuI98=
github.com/cheggaaa/pb v2.0.7+incompatible h1:gLKifR1UkZ/kLkda5gC0K6c8g+jU2sINPtBeOiNlMhU=
github.com/cheggaaa/pb/v3 v3.0.4 h1:QZEPYOj2ix6d5oEg63fbHmpolrnNiwjUsk+h74Yt4bM=
github.com/cheggaaa/pb/v3 v3.0.4/go.mod h1:7rgWxLrAUcFMkvJuv09+DYi7mMUYi8nO9iOWcvGJPfw=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
7 changes: 6 additions & 1 deletion hw07_file_copying/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"flag"
"log"
)

var (
Expand All @@ -18,5 +19,9 @@ func init() {

func main() {
flag.Parse()
// Place your code here

err := Copy(from, to, offset, limit)
if err != nil {
log.Fatal(err)
}
}