UNPKG

aux-dbf

Version:

DBF for price PSM

255 lines (217 loc) 8.28 kB
import { Column, COLUMN_TYPE } from "./Column"; import { Row } from "./Row"; import { NodeIndex } from "./NodeIndex"; import { isUndefined } from "util"; import { BTree } from "./BTree"; import { DBF_TABLE_TYPE } from "./DBF_TABLE_TYPE"; import { DBF_MODE } from "./DBF_MODE"; import { DBFReader } from "./DBFReader"; import { DBF4Reader } from "./DBF4Reader"; import { DBF7Reader } from "./DBF7Reader"; const iconv = require("iconv-lite"); var fs = require("fs"); /** * Проверять, является ли переменная val строкой * @param val * @return {boolean} */ function isString(val) { return (typeof val === "string" || val instanceof String); } /** * DZHIGURDA A. (c) 2017 * OOO "PIKADA-LAB" * Version 0.0.3-DEV */ export class DBFLib { /** Счётчик символов */ private i: number; /** Сколько в строке символов */ private iLine: number; // Заголовочные данные /** Тип таблицы */ public TypeTable: DBF_TABLE_TYPE; private RecordsCount: number; /** Полная длина заголовка включая дескриптор */ private HeaderSize: number; /** Длина одной записи */ private RecordSize: number; /** Наличие кодировки */ private Encode: number; // Сигнатура /** Кол-во колонок */ private countColumn: number; // Кол-во колонок /** Ссылка на файл */ private file: File; /** Колонки */ private col: Column[]; /** Данные */ private data: Row[]; /** Массив индексов */ private indexes: BTree[]; public mode: DBF_MODE = DBF_MODE.PROD; private binFile: Buffer; protected reader: DBFReader; protected dataSource: any[][] = []; constructor(private path: string) {} public DBFRead(clbk?: (err: any, dbf: DBFLib) => void): void { try { if (this.mode == DBF_MODE.TEST) { console.log("[*] OpenFile. " + this.path + "\n"); } fs.readFile(this.path, (err: any, file: Buffer) => { if (err) { if (err.code === "ENOENT") { console.log(this.path + " не найден"); if (!isUndefined(clbk)) clbk(this.path + " не найден", null); return; } if (!isUndefined(clbk)) clbk(err, null); return; } if (file.length == 0) return; this.binFile = file; if (this.mode == DBF_MODE.TEST) { console.time("read row"); } this.checkTableType(); if (this.TypeTable == 3) { this.reader = new DBF4Reader(file); } else if (this.TypeTable == 4) { this.reader = new DBF7Reader(file); } else { throw new Error("Формат DBF не поддерживается"); } this.reader.mode = this.mode; this.reader.readHeader(); this.reader.readSignature(); this.col = this.reader.getColumns(); this.countColumn = this.col.length; if (this.mode == DBF_MODE.TEST) { console.timeEnd("read row"); } if (!isUndefined(clbk)) clbk(err, this); }); } catch (ex) { if (!isUndefined(clbk)) clbk(ex, null); } } public readRows() { this.dataSource = this.reader.readTable(); this.indexes = new Array(this.Count()).fill(null); } public Exist(): boolean { return this.file != null; } /** Название стобца по номеру */ public getRowName(index: number): string { return this.col[index].getTitle(); } /** Строка по номеру строки и номеру столбца */ public getRow(rowIndex: number, colIndex: number | string): string | Buffer { if (rowIndex == null || colIndex == null) { throw "Индекс не определён " + rowIndex + "x" + colIndex; } this.checkRow(rowIndex); if ( isString(colIndex) ) { colIndex = (colIndex as string).toLowerCase(); let l = 0; for (l = 0; l < this.countColumn; l++) { if (this.col[l].getTitle().toLowerCase() == colIndex) break; } if (l == this.countColumn) throw "Индекс за пределом доступного количества колонок. Доступное значение от 0 до " + (this.col.length - 1); return this.data[rowIndex][l]; } else { if (!this.checkColumn(+colIndex)) throw "Индекс за пределом доступного количества колонок. Доступное значение от 0 до " + (this.col.length - 1); return this.dataSource[rowIndex][colIndex]; } } public getString(rowIndex: number, colIndex: number | string) { if (isString(colIndex)) { colIndex = (colIndex as string).toLowerCase(); let l = 0; for (l = 0; l < this.countColumn; l++) { if (this.col[l].getTitle().toLowerCase() == colIndex) break; } if (l == this.countColumn) throw "Индекс за пределом доступного количества колонок. Доступное значение от 0 до " + (this.col.length - 1); colIndex = l; } if (this.getRow(rowIndex, colIndex) instanceof Buffer) { return iconv.decode(Buffer.from(this.getRow(rowIndex, colIndex) as string, "binary"), "win1251").trim(); } else { this.checkAccess(rowIndex, colIndex); return this.getRow(rowIndex, colIndex).toString(); } } public getInt(rowIndex: number, colIndex: number | string): number { if (isString(colIndex)) { colIndex = (colIndex as string).toLowerCase(); let l = 0; for (l = 0; l < this.countColumn; l++) { if (this.col[l].getTitle().toLowerCase() == colIndex) break; } if (l == this.countColumn) throw "Индекс за пределом доступного количества колонок. Доступное значение от 0 до " + (this.col.length - 1); this.checkAccess(rowIndex, l); return +this.dataSource[rowIndex][l]; } else { this.checkAccess(rowIndex, colIndex); return +this.dataSource[rowIndex][colIndex]; } // return +this.data[rowIndex].value[colIndex]; } private checkAccess(rowIndex, colIndex) { if (!this.checkRow(rowIndex)) throw "Индекс за пределом доступного количества строк. Доступное значение от 0 до " + (this.Count() - 1); if (!this.checkColumn(colIndex)) throw "Индекс за пределом доступного количества колонок. Доступное значение от 0 до " + (this.CountColumn() - 1); } /** Количество строк */ public Count(): number { return this.dataSource.length; } /** Количество колонок */ public CountColumn(): number { return this.col.length; } public SetBTree(columnIndex: number): void { if (this.mode == DBF_MODE.TEST) { console.time("add index " + columnIndex); } this.indexes[columnIndex] = new BTree(); for (let i = 0; i < this.Count(); i++) { this.indexes[columnIndex].insert(this.getInt(i, columnIndex), i); } if (this.mode == DBF_MODE.TEST) { console.timeEnd("add index " + columnIndex); } } public Search(l: number, value: number): number { let i: number; if (this.indexes[l]) { // console.log("[*] Whith index"); const index: NodeIndex = this.indexes[l].search(value); if (!index) return null; const i: number = index.Adress; if (!i) return null; return i; } // console.log("[X] Whith index"); for (let key = 0; key < this.Count(); key++) { if (this.getInt(key, l) == value) { return key; } } return null; } /// PRIVATE private checkRow(index: number) { return index < this.dataSource.length; } private checkColumn(index: number) { return index < this.col.length; } /** * Задаёт байт для определения типа таблицы */ private checkTableType(): void { this.TypeTable = this.binFile.readInt8(0); } }