diff --git a/binary_read.go b/binary_read.go
new file mode 100644
index 0000000..598ab81
--- /dev/null
+++ b/binary_read.go
@@ -0,0 +1,86 @@
+package xls
+
+import (
+	"encoding/binary"
+	"io"
+)
+
+func ReadBytes(r io.Reader, size int) ([]byte, error) {
+	buf := make([]byte, size)
+	if _, err := r.Read(buf); err != nil {
+		return buf, err
+	}
+	return buf, nil
+}
+
+func MustReadBytes(r io.Reader, size int) []byte {
+	buf, _ := ReadBytes(r, size)
+	return buf
+}
+
+func ReadByte(r io.Reader) (byte, error) {
+	buf, err := ReadBytes(r, 1)
+	if err != nil {
+		return 0, err
+	}
+	return buf[0], nil
+}
+
+func ReadUint16(r io.Reader) (uint16, error) {
+	buf, err := ReadBytes(r, 2)
+	if err != nil {
+		return 0, err
+	}
+	return binary.LittleEndian.Uint16(buf), nil
+}
+
+func ReadUint32(r io.Reader) (uint32, error) {
+	buf, err := ReadBytes(r, 4)
+	if err != nil {
+		return 0, err
+	}
+	return binary.LittleEndian.Uint32(buf), nil
+}
+
+func ReadBoundSheet(r io.Reader) *boundsheet {
+	var bs = new(boundsheet)
+	buf, _ := ReadBytes(r, 7)
+	bs.Filepos = binary.LittleEndian.Uint32(buf[0:4])
+	bs.Visible = buf[4]
+	bs.Type = buf[5]
+	bs.Name = buf[6]
+	return bs
+}
+
+func ReadRowInfo(r io.Reader) *rowInfo {
+	row := new(rowInfo)
+	buf, _ := ReadBytes(r, 16)
+	row.Index = binary.LittleEndian.Uint16(buf[0:2])
+	row.Fcell = binary.LittleEndian.Uint16(buf[2:4])
+	row.Lcell = binary.LittleEndian.Uint16(buf[4:6])
+	row.Height = binary.LittleEndian.Uint16(buf[6:8])
+	row.Notused = binary.LittleEndian.Uint16(buf[8:10])
+	row.Notused2 = binary.LittleEndian.Uint16(buf[10:12])
+	row.Flags = binary.LittleEndian.Uint32(buf[12:16])
+	return row
+}
+
+func ReadLabelsstCol(r io.Reader) *LabelsstCol {
+	col := new(LabelsstCol)
+	buf, _ := ReadBytes(r, 10)
+	col.RowB = binary.LittleEndian.Uint16(buf[0:2])
+	col.FirstColB = binary.LittleEndian.Uint16(buf[2:4])
+	col.Xf = binary.LittleEndian.Uint16(buf[4:6])
+	col.Sst = binary.LittleEndian.Uint32(buf[6:10])
+	return col
+}
+
+func ReadBof(r io.Reader, row *bof) error {
+	buf, err := ReadBytes(r, 4)
+	if err != nil {
+		return err
+	}
+	row.Id = binary.LittleEndian.Uint16(buf[0:2])
+	row.Size = binary.LittleEndian.Uint16(buf[2:4])
+	return err
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..1a5cb69
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,10 @@
+module github.com/extrame/xls
+
+go 1.16
+
+require (
+	github.com/extrame/goyymmdd v0.0.0-20210114090516-7cc815f00d1a
+	github.com/extrame/ole2 v0.0.0-20160812065207-d69429661ad7
+	github.com/tealeg/xlsx v1.0.5
+	golang.org/x/text v0.3.7
+)
diff --git a/workbook.go b/workbook.go
index f917d53..aa10448 100644
--- a/workbook.go
+++ b/workbook.go
@@ -45,7 +45,8 @@ func (w *WorkBook) Parse(buf io.ReadSeeker) {
 	// buf := bytes.NewReader(bts)
 	offset := 0
 	for {
-		if err := binary.Read(buf, binary.LittleEndian, b); err == nil {
+		//if err := binary.Read(buf, binary.LittleEndian, b); err == nil {
+		if err := ReadBof(buf, b); err == nil {
 			bof_pre, b, offset = w.parseBof(buf, b, bof_pre, offset)
 		} else {
 			break
@@ -72,8 +73,9 @@ func (w *WorkBook) addFormat(format *Format) {
 func (wb *WorkBook) parseBof(buf io.ReadSeeker, b *bof, pre *bof, offset_pre int) (after *bof, after_using *bof, offset int) {
 	after = b
 	after_using = pre
-	var bts = make([]byte, b.Size)
-	binary.Read(buf, binary.LittleEndian, bts)
+	//var bts = make([]byte, b.Size)
+	//binary.Read(buf, binary.LittleEndian, bts)
+	var bts = MustReadBytes(buf, int(b.Size))
 	buf_item := bytes.NewReader(bts)
 	switch b.Id {
 	case 0x809:
@@ -135,7 +137,8 @@ func (wb *WorkBook) parseBof(buf io.ReadSeeker, b *bof, pre *bof, offset_pre int
 		offset = i
 	case 0x85: // boundsheet
 		var bs = new(boundsheet)
-		binary.Read(buf_item, binary.LittleEndian, bs)
+		//binary.Read(buf_item, binary.LittleEndian, bs)
+		bs = ReadBoundSheet(buf_item)
 		// different for BIFF5 and BIFF8
 		wb.addSheet(bs, buf_item)
 	case 0x0e0: // XF
@@ -177,15 +180,18 @@ func (w *WorkBook) get_string(buf io.ReadSeeker, size uint16) (res string, err e
 		var richtext_num = uint16(0)
 		var phonetic_size = uint32(0)
 		var flag byte
-		err = binary.Read(buf, binary.LittleEndian, &flag)
+		//err = binary.Read(buf, binary.LittleEndian, &flag)
+		flag, err = ReadByte(buf)
 		if flag&0x8 != 0 {
-			err = binary.Read(buf, binary.LittleEndian, &richtext_num)
+			//err = binary.Read(buf, binary.LittleEndian, &richtext_num)
+			richtext_num, err = ReadUint16(buf)
 		} else if w.continue_rich > 0 {
 			richtext_num = w.continue_rich
 			w.continue_rich = 0
 		}
 		if flag&0x4 != 0 {
-			err = binary.Read(buf, binary.LittleEndian, &phonetic_size)
+			//err = binary.Read(buf, binary.LittleEndian, &phonetic_size)
+			phonetic_size, err = ReadUint32(buf)
 		} else if w.continue_apsb > 0 {
 			phonetic_size = w.continue_apsb
 			w.continue_apsb = 0
@@ -194,7 +200,8 @@ func (w *WorkBook) get_string(buf io.ReadSeeker, size uint16) (res string, err e
 			var bts = make([]uint16, size)
 			var i = uint16(0)
 			for ; i < size && err == nil; i++ {
-				err = binary.Read(buf, binary.LittleEndian, &bts[i])
+				//err = binary.Read(buf, binary.LittleEndian, &bts[i])
+				bts[i], err = ReadUint16(buf)
 			}
 
 			// when eof found, we dont want to append last element
@@ -226,15 +233,16 @@ func (w *WorkBook) get_string(buf io.ReadSeeker, size uint16) (res string, err e
 			res = string(runes)
 		}
 		if richtext_num > 0 {
-			var bts []byte
+			//var bts []byte
 			var seek_size int64
 			if w.Is5ver {
 				seek_size = int64(2 * richtext_num)
 			} else {
 				seek_size = int64(4 * richtext_num)
 			}
-			bts = make([]byte, seek_size)
-			err = binary.Read(buf, binary.LittleEndian, bts)
+			//bts = make([]byte, seek_size)
+			//err = binary.Read(buf, binary.LittleEndian, bts)
+			_, err = ReadBytes(buf, int(seek_size))
 			if err == io.EOF {
 				w.continue_rich = richtext_num
 			}
@@ -242,9 +250,10 @@ func (w *WorkBook) get_string(buf io.ReadSeeker, size uint16) (res string, err e
 			// err = binary.Read(buf, binary.LittleEndian, bts)
 		}
 		if phonetic_size > 0 {
-			var bts []byte
-			bts = make([]byte, phonetic_size)
-			err = binary.Read(buf, binary.LittleEndian, bts)
+			//var bts []byte
+			//bts = make([]byte, phonetic_size)
+			//err = binary.Read(buf, binary.LittleEndian, bts)
+			_, err = ReadBytes(buf, int(phonetic_size))
 			if err == io.EOF {
 				w.continue_apsb = phonetic_size
 			}
diff --git a/worksheet.go b/worksheet.go
index 0f4ec8b..ffa7159 100644
--- a/worksheet.go
+++ b/worksheet.go
@@ -51,7 +51,8 @@ func (w *WorkSheet) parse(buf io.ReadSeeker) {
 	var bof_pre *bof
 	var col_pre interface{}
 	for {
-		if err := binary.Read(buf, binary.LittleEndian, b); err == nil {
+		//if err := binary.Read(buf, binary.LittleEndian, b); err == nil {
+		if err := ReadBof(buf, b); err == nil {
 			bof_pre, col_pre = w.parseBof(buf, b, bof_pre, col_pre)
 			if b.Id == 0xa {
 				break
@@ -81,8 +82,9 @@ func (w *WorkSheet) parseBof(buf io.ReadSeeker, b *bof, pre *bof, col_pre interf
 		w.rightToLeft = (sheetOptions & 0x40) != 0
 		w.Selected = (sheetOptions & 0x400) != 0
 	case 0x208: //ROW
-		r := new(rowInfo)
-		binary.Read(buf, binary.LittleEndian, r)
+		//r := new(rowInfo)
+		//binary.Read(buf, binary.LittleEndian, r)
+		r := ReadRowInfo(buf)
 		w.addRow(r)
 	case 0x0BD: //MULRK
 		mc := new(MulrkCol)
@@ -129,8 +131,9 @@ func (w *WorkSheet) parseBof(buf io.ReadSeeker, b *bof, pre *bof, col_pre interf
 		col = new(RkCol)
 		binary.Read(buf, binary.LittleEndian, col)
 	case 0xFD: //LABELSST
-		col = new(LabelsstCol)
-		binary.Read(buf, binary.LittleEndian, col)
+		//col = new(LabelsstCol)
+		//binary.Read(buf, binary.LittleEndian, col)
+		col = ReadLabelsstCol(buf)
 	case 0x204:
 		c := new(labelCol)
 		binary.Read(buf, binary.LittleEndian, &c.BlankCol)