aux-dbf
Version:
DBF for price PSM
132 lines (118 loc) • 4.23 kB
text/typescript
import { DBFReader } from "./DBFReader";
import { DBF_MODE } from "./DBF_MODE";
import { Column, COLUMN_TYPE } from "./Column";
const iconv = require("iconv-lite");
export class DBF4Reader extends DBFReader {
protected sizeFieldDescriptior = 32;
protected sizeHeadLength = 32;
readHeader() {
this.TypeTable = this.file.readInt8(0);
this.DateHeaderY = this.file.readInt8(1) - 100 + 2000;
this.DateHeaderM = this.file.readInt8(2);
this.DateHeaderD = this.file.readInt8(3) % 31;
this.RecordsCount = this.file.readInt32LE(4);
this.HeaderSize = this.file.readInt16LE(8);
this.RecordSize = this.file.readInt16LE(10);
this.Encode = this.file.readInt8(29);
this.ColumnCount =
(this.HeaderSize - this.sizeHeadLength - 1) / this.sizeFieldDescriptior;
if (this.mode == DBF_MODE.TEST) {
this.printHeader();
}
}
readSignature() {
this.columns = Array(this.ColumnCount)
.fill(new Column())
.map<Column>((_) => new Column())
.map<Column>((column, index) => {
let offset = index * this.sizeHeadLength + this.sizeFieldDescriptior;
let name = this.file
.slice(offset, offset + 10)
.filter((r) => r != 0)
.toString();
let size = this.file.readUInt8(offset + 16);
let type = this.readChar(offset + 11) as COLUMN_TYPE;
let decimalPlaces = this.file.readUInt8(offset + 17);
let isMDX = this.file.readUInt8(offset + 31).toString() != "0";
column.Add(name, size, type, index, decimalPlaces, isMDX);
return column;
});
if (this.mode == DBF_MODE.TEST) {
this.printColumns();
}
}
readTable(): any[][] {
console.time("READ DATA SOURCE");
let array = Array(this.RecordsCount)
.fill(new Array(this.ColumnCount).fill(null))
.map((r) => {
return new Array(this.ColumnCount);
});
const startPosition = this.HeaderSize;
let offsetLeft = 0;
for (let column = 0; column < this.ColumnCount; column++) {
let position = startPosition + 1;
if (this.columns[column].getType() == COLUMN_TYPE.CHARACTER) {
let size = this.columns[column].getSize();
for (let row = 0; row < this.RecordsCount; row++) {
// TODO
array[row][column] =
//iconv.decode(
this.file.subarray(
position + offsetLeft,
position + offsetLeft + size
);
//, "win1251" ).trim();
position += this.RecordSize;
}
} else if (this.columns[column].getType() == COLUMN_TYPE.NUMBER) {
let size = this.columns[column].getSize();
for (let row = 0; row < this.RecordsCount; row++) {
array[row][column] = +this.file.toString(
"ascii",
position + offsetLeft,
position + offsetLeft + size
);
position += this.RecordSize;
}
} else if (this.columns[column].getType() == COLUMN_TYPE.FLOAT) {
let size = this.columns[column].getSize();
for (let row = 0; row < this.RecordsCount; row++) {
array[row][column] = +this.file.toString(
"ascii",
position + offsetLeft,
position + offsetLeft + size
);
position += this.RecordSize;
}
} else if (this.columns[column].getType() == COLUMN_TYPE.DATE) {
for (let row = 0; row < this.RecordsCount; row++) {
array[row][column] = this.readDate(
this.file.subarray(position + offsetLeft, position + offsetLeft + 8)
);
let p = position + offsetLeft;
position += this.RecordSize;
}
} else {
throw new Error("[X] Непредсказуемый тип колонки");
}
offsetLeft += this.columns[column].getSize();
}
console.timeEnd("READ DATA SOURCE");
return array;
}
private readDate(buffer: Buffer) {
let date = (
buffer.toString("ascii", 0, 4) +
"-" +
buffer.toString("ascii", 4, 6) +
"-" +
buffer.toString("ascii", 6, 8)
);
if(/(\d{4}-\d{2}-\d{2})/.test(date)) {
return date;
} else {
return "0000-00-00";
}
}
}