- 自己动手写Java虚拟机
- 张秀宏
- 441字
- 2023-01-30 16:12:47
2.3.3 ZipEntry
ZipEntry表示ZIP或JAR文件形式的类路径。在ch02\classpath目录下创建entry_zip. go文件,在其中定义ZipEntry结构体,代码如下:
package classpath import "archive/zip" import "errors" import "io/ioutil" import "path/filepath" type ZipEntry struct { absPath string } func newZipEntry(path string) *ZipEntry {...} func (self *ZipEntry) readClass(className string) ([]byte, Entry, error) {...} func (self *ZipEntry) String() string {...}
absPath字段存放ZIP或JAR文件的绝对路径。构造函数和String()与DirEntry大同小异,就不多解释了,代码如下:
func newZipEntry(path string) *ZipEntry { absPath, err := filepath.Abs(path) if err ! = nil { panic(err) } return &ZipEntry{absPath} } func (self *ZipEntry) String() string { return self.absPath }
下面重点介绍如何从ZIP文件中提取class文件,代码如下:
func (self *ZipEntry) readClass(className string) ([]byte, Entry, error) { r, err := zip.OpenReader(self.absPath) if err ! = nil { return nil, nil, err } defer r.Close() for _, f := range r.File { if f.Name == className { rc, err := f.Open() if err ! = nil { return nil, nil, err } defer rc.Close() data, err := ioutil.ReadAll(rc) if err ! = nil { return nil, nil, err } return data, self, nil } } return nil, nil, errors.New("class not found: " + className) }
首先打开ZIP文件,如果这一步出错的话,直接返回。然后遍历ZIP压缩包里的文件,看能否找到class文件。如果能找到,则打开class文件,把内容读取出来,并返回。如果找不到,或者出现其他错误,则返回错误信息。有两处使用了defer语句来确保打开的文件得以关闭。readClass()方法每次都要打开和关闭ZIP文件,因此效率不是很高。笔者进行了优化,但鉴于篇幅有限,就不展示具体代码了。感兴趣的读者可以阅读ch02\classpath\entry_zip2.go文件。