// ReadBytes reads bytes from a data object at the specified position and length, returns []byte slice and error. func (obj *DataObj) ReadBytes(pos int64, length int) ([]byte, error) { if er := obj.init(); er != nil { return nil, er } var ( buffer C.bytesBuf_t err *C.char bytesRead C.int ) if er := obj.LSeek(pos); er != nil { return nil, er } ccon := obj.con.GetCcon() defer obj.con.ReturnCcon(ccon) if status := C.gorods_read_dataobject(obj.chandle, C.rodsLong_t(length), &buffer, &bytesRead, ccon, &err); status != 0 { return nil, newError(Fatal, fmt.Sprintf("iRODS ReadBytes DataObject Failed: %v, %v", obj.path, C.GoString(err))) } buf := unsafe.Pointer(buffer.buf) defer C.free(buf) data := C.GoBytes(buf, bytesRead) return data, nil }
// ReadChunk reads the entire data object in chunks (size of chunk specified by size parameter), passing the data into a callback function for each chunk. Use this to read/write large files. func (obj *DataObj) ReadChunk(size int64, callback func([]byte)) error { if er := obj.init(); er != nil { return er } var ( buffer C.bytesBuf_t err *C.char bytesRead C.int ) if er := obj.LSeek(0); er != nil { return er } for obj.offset < obj.size { ccon := obj.con.GetCcon() if status := C.gorods_read_dataobject(obj.chandle, C.rodsLong_t(size), &buffer, &bytesRead, ccon, &err); status != 0 { obj.con.ReturnCcon(ccon) return newError(Fatal, fmt.Sprintf("iRODS Read DataObject Failed: %v, %v", obj.path, C.GoString(err))) } obj.con.ReturnCcon(ccon) buf := unsafe.Pointer(buffer.buf) chunk := C.GoBytes(buf, bytesRead) C.free(buf) callback(chunk) if er := obj.LSeek(obj.offset + size); er != nil { return er } } if er := obj.LSeek(0); er != nil { return er } return obj.Close() }