Skip to content

Commit c879cfb

Browse files
committed
update
1 parent e48936a commit c879cfb

File tree

3 files changed

+353
-325
lines changed

3 files changed

+353
-325
lines changed

archive.go

+335
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
package com
2+
3+
import (
4+
"archive/tar"
5+
"archive/zip"
6+
"compress/gzip"
7+
"fmt"
8+
"io"
9+
"os"
10+
"path/filepath"
11+
"regexp"
12+
"strings"
13+
)
14+
15+
// Zip 压缩为zip
16+
// args: regexpFileName, regexpIgnoreFile
17+
func Zip(srcDirPath string, destFilePath string, args ...*regexp.Regexp) (n int64, err error) {
18+
root, err := filepath.Abs(srcDirPath)
19+
if err != nil {
20+
return 0, err
21+
}
22+
23+
f, err := os.Create(destFilePath)
24+
if err != nil {
25+
return
26+
}
27+
defer f.Close()
28+
29+
w := zip.NewWriter(f)
30+
var regexpIgnoreFile, regexpFileName *regexp.Regexp
31+
argLen := len(args)
32+
if argLen > 1 {
33+
regexpIgnoreFile = args[1]
34+
regexpFileName = args[0]
35+
} else if argLen == 1 {
36+
regexpFileName = args[0]
37+
}
38+
err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
39+
if err != nil {
40+
return err
41+
}
42+
if regexpIgnoreFile != nil && (regexpIgnoreFile.MatchString(info.Name()) || regexpIgnoreFile.MatchString(path)) {
43+
if info.IsDir() {
44+
return filepath.SkipDir
45+
}
46+
return nil
47+
} else if info.IsDir() {
48+
return nil
49+
}
50+
if regexpFileName != nil && (!regexpFileName.MatchString(info.Name()) && !regexpFileName.MatchString(path)) {
51+
return nil
52+
}
53+
relativePath := strings.TrimPrefix(path, root)
54+
relativePath = strings.Replace(relativePath, `\`, `/`, -1)
55+
relativePath = strings.TrimPrefix(relativePath, `/`)
56+
f, err := w.Create(relativePath)
57+
if err != nil {
58+
return err
59+
}
60+
sf, err := os.Open(path)
61+
if err != nil {
62+
return err
63+
}
64+
defer sf.Close()
65+
_, err = io.Copy(f, sf)
66+
return err
67+
})
68+
69+
err = w.Close()
70+
if err != nil {
71+
return 0, err
72+
}
73+
74+
fi, err := f.Stat()
75+
if err != nil {
76+
n = fi.Size()
77+
}
78+
return
79+
}
80+
81+
// Unzip unzips .zip file to 'destPath'.
82+
// It returns error when fail to finish operation.
83+
func Unzip(srcPath, destPath string) error {
84+
// Open a zip archive for reading
85+
r, err := zip.OpenReader(srcPath)
86+
if err != nil {
87+
return err
88+
}
89+
defer r.Close()
90+
91+
// Iterate through the files in the archive
92+
for _, f := range r.File {
93+
// Get files from archive
94+
rc, err := f.Open()
95+
if err != nil {
96+
return err
97+
}
98+
99+
dir := filepath.Dir(f.Name)
100+
// Create directory before create file
101+
os.MkdirAll(destPath+"/"+dir, os.ModePerm)
102+
103+
if f.FileInfo().IsDir() {
104+
continue
105+
}
106+
107+
// Write data to file
108+
var fw *os.File
109+
fw, err = os.Create(filepath.Join(destPath, f.Name))
110+
if err != nil {
111+
return err
112+
}
113+
_, err = io.Copy(fw, rc)
114+
fw.Close()
115+
rc.Close()
116+
if err != nil {
117+
return err
118+
}
119+
}
120+
return nil
121+
}
122+
123+
// TarGz 压缩为tar.gz
124+
// args: regexpFileName, regexpIgnoreFile
125+
func TarGz(srcDirPath string, destFilePath string, args ...*regexp.Regexp) error {
126+
fw, err := os.Create(destFilePath)
127+
if err != nil {
128+
return err
129+
}
130+
defer fw.Close()
131+
// Gzip writer
132+
gw := gzip.NewWriter(fw)
133+
err = tarGz(gw, srcDirPath, args...)
134+
gw.Close()
135+
return err
136+
}
137+
138+
func TarGzWithLevel(compressLevel int, srcDirPath string, destFilePath string, args ...*regexp.Regexp) error {
139+
fw, err := os.Create(destFilePath)
140+
if err != nil {
141+
return err
142+
}
143+
defer fw.Close()
144+
// Gzip writer
145+
var gw *gzip.Writer
146+
gw, err = gzip.NewWriterLevel(fw, compressLevel)
147+
if err != nil {
148+
return err
149+
}
150+
err = tarGz(gw, srcDirPath, args...)
151+
gw.Close()
152+
return err
153+
}
154+
155+
func tarGz(gw *gzip.Writer, srcDirPath string, args ...*regexp.Regexp) error {
156+
// Tar writer
157+
tw := tar.NewWriter(gw)
158+
defer tw.Close()
159+
160+
// Check if it's a file or a directory
161+
f, err := os.Open(srcDirPath)
162+
if err != nil {
163+
return err
164+
}
165+
fi, err := f.Stat()
166+
if err != nil {
167+
return err
168+
}
169+
if fi.IsDir() {
170+
var regexpIgnoreFile, regexpFileName *regexp.Regexp
171+
argLen := len(args)
172+
if argLen > 1 {
173+
regexpIgnoreFile = args[1]
174+
regexpFileName = args[0]
175+
} else if argLen == 1 {
176+
regexpFileName = args[0]
177+
}
178+
// handle source directory
179+
fmt.Println("Cerating tar.gz from directory...")
180+
if err := tarGzDir(srcDirPath, filepath.Base(srcDirPath), tw, regexpFileName, regexpIgnoreFile); err != nil {
181+
return err
182+
}
183+
} else {
184+
// handle file directly
185+
fmt.Println("Cerating tar.gz from " + fi.Name() + "...")
186+
if err := tarGzFile(srcDirPath, fi.Name(), tw, fi); err != nil {
187+
return err
188+
}
189+
}
190+
fmt.Println("Well done!")
191+
return err
192+
}
193+
194+
// Deal with directories
195+
// if find files, handle them with tarGzFile
196+
// Every recurrence append the base path to the recPath
197+
// recPath is the path inside of tar.gz
198+
func tarGzDir(srcDirPath string, recPath string, tw *tar.Writer, regexpFileName, regexpIgnoreFile *regexp.Regexp) error {
199+
// Open source diretory
200+
dir, err := os.Open(srcDirPath)
201+
if err != nil {
202+
return err
203+
}
204+
defer dir.Close()
205+
206+
// Get file info slice
207+
fis, err := dir.Readdir(0)
208+
if err != nil {
209+
return err
210+
}
211+
for _, fi := range fis {
212+
// Append path
213+
curPath := srcDirPath + "/" + fi.Name()
214+
if regexpIgnoreFile != nil && (regexpIgnoreFile.MatchString(fi.Name()) || regexpIgnoreFile.MatchString(curPath)) {
215+
continue
216+
}
217+
if regexpFileName != nil && (!regexpFileName.MatchString(fi.Name()) && !regexpFileName.MatchString(curPath)) {
218+
continue
219+
}
220+
// Check it is directory or file
221+
if fi.IsDir() {
222+
// Directory
223+
// (Directory won't add unitl all subfiles are added)
224+
fmt.Printf("Adding path...%s\n", curPath)
225+
tarGzDir(curPath, recPath+"/"+fi.Name(), tw, regexpFileName, regexpIgnoreFile)
226+
} else {
227+
// File
228+
fmt.Printf("Adding file...%s\n", curPath)
229+
}
230+
231+
tarGzFile(curPath, recPath+"/"+fi.Name(), tw, fi)
232+
}
233+
return err
234+
}
235+
236+
// Deal with files
237+
func tarGzFile(srcFile string, recPath string, tw *tar.Writer, fi os.FileInfo) error {
238+
if fi.IsDir() {
239+
// Create tar header
240+
hdr := new(tar.Header)
241+
// if last character of header name is '/' it also can be directory
242+
// but if you don't set Typeflag, error will occur when you untargz
243+
hdr.Name = recPath + "/"
244+
hdr.Typeflag = tar.TypeDir
245+
hdr.Size = 0
246+
//hdr.Mode = 0755 | c_ISDIR
247+
hdr.Mode = int64(fi.Mode())
248+
hdr.ModTime = fi.ModTime()
249+
250+
// Write hander
251+
err := tw.WriteHeader(hdr)
252+
if err != nil {
253+
return err
254+
}
255+
} else {
256+
// File reader
257+
fr, err := os.Open(srcFile)
258+
if err != nil {
259+
return err
260+
}
261+
defer fr.Close()
262+
263+
// Create tar header
264+
hdr := new(tar.Header)
265+
hdr.Name = recPath
266+
hdr.Size = fi.Size()
267+
hdr.Mode = int64(fi.Mode())
268+
hdr.ModTime = fi.ModTime()
269+
270+
// Write hander
271+
err = tw.WriteHeader(hdr)
272+
if err != nil {
273+
return err
274+
}
275+
276+
// Write file data
277+
_, err = io.Copy(tw, fr)
278+
if err != nil {
279+
return err
280+
}
281+
}
282+
return nil
283+
}
284+
285+
// UnTarGz ungzips and untars .tar.gz file to 'destPath' and returns sub-directories.
286+
// It returns error when fail to finish operation.
287+
func UnTarGz(srcFilePath string, destDirPath string) ([]string, error) {
288+
// Create destination directory
289+
os.Mkdir(destDirPath, os.ModePerm)
290+
291+
fr, err := os.Open(srcFilePath)
292+
if err != nil {
293+
return nil, err
294+
}
295+
defer fr.Close()
296+
297+
// Gzip reader
298+
gr, err := gzip.NewReader(fr)
299+
if err != nil {
300+
return nil, err
301+
}
302+
defer gr.Close()
303+
304+
// Tar reader
305+
tr := tar.NewReader(gr)
306+
307+
dirs := make([]string, 0, 5)
308+
for {
309+
hdr, err := tr.Next()
310+
if err == io.EOF {
311+
// End of tar archive
312+
break
313+
}
314+
315+
// Check if it is directory or file
316+
if hdr.Typeflag != tar.TypeDir {
317+
// Get files from archive
318+
// Create directory before create file
319+
dir := filepath.Dir(hdr.Name)
320+
os.MkdirAll(destDirPath+"/"+dir, os.ModePerm)
321+
dirs = AppendStr(dirs, dir)
322+
323+
// Write data to file
324+
fw, _ := os.Create(destDirPath + "/" + hdr.Name)
325+
if err != nil {
326+
return nil, err
327+
}
328+
_, err = io.Copy(fw, tr)
329+
if err != nil {
330+
return nil, err
331+
}
332+
}
333+
}
334+
return dirs, nil
335+
}

archive_test.go

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestZip(t *testing.T) {
11+
MkdirAll(`testdata`, os.ModePerm)
12+
n, err := Zip(`./encoding`, `testdata/test.zip`)
13+
assert.NoError(t, err)
14+
assert.NotEqual(t, n, 0)
15+
16+
err = Unzip(`testdata/test.zip`, `testdata/unarchive`)
17+
assert.NoError(t, err)
18+
}

0 commit comments

Comments
 (0)