1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
function uints(reader,offset,length){
	if(offset===null) offset = reader.__pos;
	else reader.__pos = Number(offset);
	reader.__pos += fs.readSync(reader.__fileSign,reader.__buffer,0,length,offset);
	return reader.__le?
		reader.__buffer.readUIntLE(0,length):
		reader.__buffer.readUIntBE(0,length);
}

FileReader = class {
	
	constructor(file,little=true){
		this.__fileSign = fs.openSync(file);
		this.__buffer = Buffer.alloc(8)
		this.__le = Boolean(little);
		this.__pos = 0;
		this.__bigPos = false; //用於標示偏移是否改採用 BigInt,需要先驗證偏移是否可以使用 BigInt 正確定位
		this.__ss = fs.statSync(file);
	}
	
	set little(v){
		this.__le = Boolean(v)
	}
	
	writeTo(file, offset, length=null){
		if(length===null) throw new Error('length required');
		if(offset===null) throw new Error('offset required');
		offset = Number(offset);
		if(length<0) length = this.__ss.size - offset;
		
		var wf = fs.openSync(file,'w');
		var buffer = Buffer.alloc(16384); //16KB
		var readed = 0;
		var remaining = length;
		
		while(remaining){
			readed = fs.readSync(
				this.__fileSign,
				buffer,
				0,
				Math.min(16384,remaining),
				offset
			);
			fs.writeSync(wf,buffer,0,readed);
			remaining -= readed;
			offset += readed;
		}
		
		fs.close(wf);
		
	}
	
	read(buffer, offset=null, length=null){
		if(length===null) length = buffer.length;
		if(offset===null) offset = this.__pos;
		else this.__pos = Number(offset);
		var readed = fs.readSync(this.__fileSign,buffer,0,length,offset);
		this.__pos += readed;
		return readed;
	}
	
	string(offset=null,length,encode){
		if(length===null) throw new Error('length required');
		var buffer = Buffer.alloc(length);
		var readed = this.read(buffer,offset,buffer.length);
		return buffer.toString(encode,0,readed).replace(/\0/g,'');
	}
	
	stringWithLength(offset=null,headerSize=2,encode){
		var length = uints(this, offset, headerSize);
		return this.string(null, length, encode);
	}
	
	byte(offset=null){
		return uints(this, offset, 1);
	}
	
	uint16(offset=null){
		return uints(this, offset, 2);
	}
	
	uint24(offset=null){
		return uints(this, offset, 3);
	}
	
	uint32(offset=null){
		return uints(this, offset, 4);
	}
	
	uint48(offset=null){
		return uints(this, offset, 6);
	}
	
	//轉換成可通用的 Number (數值過大將導致失真)
	uint64n(offset=null){
		return Number(this.uint64b(offset));
	}
	
	//以 BigInt 表示
	uint64b(offset=null){
		this.read(this.__buffer,offset);
		if(this.__le){
			for(var i=0,j=7; i<4; i++,j--){
				var s = this.__buffer[i];
				this.__buffer[i] = this.__buffer[j];
				this.__buffer[j] = s;
			}
		}
		return BigInt('0x'+this.__buffer.toString('hex'));
	}
	
	moveTo(offset=0){
		this.pos = offset;
	}
	
	skip(length=1){
		this.pos += length;
	}
	
	close(){
		fs.closeSync(this.__fileSign);
		this.__fileSign = null;
		this.__buffer = null;
		this.__ss = null;
	}
	
}