csvManager.ts 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. import { _decorator } from "cc";
  2. const { ccclass, property } = _decorator;
  3. var CELL_DELIMITERS = [",", ";", "\t", "|", "^"];
  4. var LINE_DELIMITERS = ["\r\n", "\r", "\n"];
  5. var getter = function (index: any) {
  6. return ("d[" + index + "]");
  7. };
  8. var getterCast = function(value: any, index: any, cast: any, d: any) {
  9. if (cast instanceof Array) {
  10. if (cast[index] === "any") {
  11. return d[index];
  12. }else if (cast[index] === "number") {
  13. return Number(d[index]);
  14. } else if (cast[index] === "boolean") {
  15. return d[index] === "true" || d[index] === "t" || d[index] === "1";
  16. } else {
  17. return d[index];
  18. }
  19. } else {
  20. if (cast === "any") {
  21. return d[index];
  22. } else if (!isNaN(Number(value))) {
  23. return Number(d[index]);
  24. } else if (value == "false" || value == "true" || value == "t" || value == "f") {
  25. return d[index] === "true" || d[index] === "t" || d[index] === "1";
  26. } else {
  27. return d[index];
  28. }
  29. }
  30. };
  31. var CSV = {
  32. STANDARD_DECODE_OPTS: {
  33. skip: 0,
  34. limit: false,
  35. header: false,
  36. cast: false,
  37. comment: ""
  38. },
  39. STANDARD_ENCODE_OPTS: {
  40. delimiter: CELL_DELIMITERS[0],
  41. newline: LINE_DELIMITERS[0],
  42. skip: 0,
  43. limit: false,
  44. header: false
  45. },
  46. quoteMark: '"',
  47. doubleQuoteMark: '""',
  48. quoteRegex: /"/g,
  49. assign: function () {
  50. var args = Array.prototype.slice.call(arguments);
  51. var base = args[0];
  52. var rest = args.slice(1);
  53. for (var i = 0, len = rest.length; i < len; i++) {
  54. for (var attr in rest[i]) {
  55. base[attr] = rest[i][attr];
  56. }
  57. }
  58. return base;
  59. },
  60. map: function (collection: any, fn: Function) {
  61. var results = [];
  62. for (var i = 0, len = collection.length; i < len; i++) {
  63. results[i] = fn(collection[i], i);
  64. }
  65. return results;
  66. },
  67. getType: function (obj: any) {
  68. return Object.prototype.toString.call(obj).slice(8, -1);
  69. },
  70. getLimit: function (limit: any, len: any) {
  71. return limit === false ? len : limit;
  72. },
  73. buildObjectConstructor: function(fields: any, sample: any, cast: any) {
  74. return function(d: any) {
  75. var object: any = new Object();
  76. var setter = function(attr: any, value: any) {
  77. return object[attr] = value;
  78. };
  79. if (cast) {
  80. fields.forEach(function(attr: any, idx: number) {
  81. setter(attr, getterCast(sample[idx], idx, cast, d));
  82. });
  83. } else {
  84. fields.forEach(function(attr: any, idx: number) {
  85. setter(attr, getterCast(sample[idx], idx, "any", d));
  86. });
  87. }
  88. return object;
  89. };
  90. },
  91. buildArrayConstructor: function(fields: any, sample: any, cast: any) {
  92. return function(d: any) {
  93. var row = new Array(sample.length);
  94. var setter = function(idx: any, value: any) {
  95. return row[idx] = value;
  96. };
  97. if (cast) {
  98. fields.forEach(function(attr: any, idx: number) {
  99. setter(attr, getterCast(sample[idx], idx, cast, d));
  100. });
  101. } else {
  102. fields.forEach(function(attr: any, idx: number) {
  103. setter(attr, getterCast(sample[idx], idx, "any", d));
  104. });
  105. }
  106. return row;
  107. };
  108. },
  109. frequency: function (coll: any, needle: any, limit: any) {
  110. if (limit === void 0) limit = false;
  111. var count = 0;
  112. var lastIndex = 0;
  113. var maxIndex = this.getLimit(limit, coll.length);
  114. while (lastIndex < maxIndex) {
  115. lastIndex = coll.indexOf(needle, lastIndex);
  116. if (lastIndex === -1) break;
  117. lastIndex += 1;
  118. count++;
  119. }
  120. return count;
  121. },
  122. mostFrequent: function (coll: any, needles: any, limit: any) {
  123. var max = 0;
  124. var detected;
  125. for (var cur = needles.length - 1; cur >= 0; cur--) {
  126. if (this.frequency(coll, needles[cur], limit) > max) {
  127. detected = needles[cur];
  128. }
  129. }
  130. return detected || needles[0];
  131. },
  132. unsafeParse: function (text: any, opts: any, fn: any) {
  133. var lines = text.split(opts.newline);
  134. if (opts.skip > 0) {
  135. lines.splice(opts.skip);
  136. }
  137. var fields;
  138. var constructor;
  139. function cells(lines: any) {
  140. var line = lines.shift();
  141. if (line.indexOf('"') >= 0) {// 含引号
  142. //找到这行完整的数据, 找到对称的双引号
  143. var lastIndex = 0;
  144. var findIndex = 0;
  145. var count = 0;
  146. while (lines.length > 0) {
  147. lastIndex = line.indexOf('"', findIndex);
  148. if (lastIndex === -1 && count % 2 === 0) break;
  149. if (lastIndex !== -1) {
  150. findIndex = lastIndex + 1;
  151. count++;
  152. } else {
  153. line = line + opts.newline + lines.shift();
  154. }
  155. }
  156. var list = [];
  157. var item;
  158. var quoteCount = 0;
  159. var start = 0;
  160. var end = 0;
  161. var length = line.length;
  162. for (var key in line) {
  163. if (!line.hasOwnProperty(key)) {
  164. continue;
  165. }
  166. let numKey = parseInt(key);
  167. var value = line[key];
  168. if (numKey === 0 && value === '"') {
  169. quoteCount++;
  170. start = 1;
  171. }
  172. if (value === '"') {
  173. quoteCount++;
  174. if (line[numKey - 1] === opts.delimiter && start === numKey) {
  175. start++;
  176. }
  177. }
  178. if (value === '"' && quoteCount % 2 === 0) {
  179. if (line[numKey + 1] === opts.delimiter || numKey + 1 === length) {
  180. end = numKey;
  181. item = line.substring(start, end);
  182. list.push(item);
  183. start = end + 2;
  184. end = start;
  185. }
  186. }
  187. if (value === opts.delimiter && quoteCount % 2 === 0) {
  188. end = numKey;
  189. if (end > start) {
  190. item = line.substring(start, end);
  191. list.push(item);
  192. start = end + 1;
  193. end = start;
  194. } else if (end === start) {
  195. list.push("");
  196. start = end + 1;
  197. end = start;
  198. }
  199. }
  200. }
  201. end = length;
  202. if (end >= start) {
  203. item = line.substring(start, end);
  204. list.push(item);
  205. }
  206. return list;
  207. } else {
  208. return line.split(opts.delimiter);
  209. }
  210. }
  211. if (opts.header) {
  212. if (opts.header === true) {
  213. opts.comment = cells(lines); // 第一行是注释
  214. opts.cast = cells(lines); // 第二行是数据类型
  215. fields = cells(lines);
  216. } else if (this.getType(opts.header) === "Array") {
  217. fields = opts.header;
  218. }
  219. constructor = this.buildObjectConstructor(fields, lines[0].split(opts.delimiter), opts.cast);
  220. } else {
  221. constructor = this.buildArrayConstructor(fields, lines[0].split(opts.delimiter), opts.cast);
  222. }
  223. while (lines.length > 0) {
  224. var row = cells(lines);
  225. if (row.length > 1) {
  226. fn(constructor(row), fields[0]);
  227. }
  228. }
  229. return true;
  230. },
  231. safeParse: function (text: any, opts: any, fn: Function) {
  232. var delimiter = opts.delimiter;
  233. var newline = opts.newline;
  234. var lines = text.split(newline);
  235. if (opts.skip > 0) {
  236. lines.splice(opts.skip);
  237. }
  238. return true;
  239. },
  240. encodeCells: function (line: any, delimiter: any, newline: any) {
  241. var row = line.slice(0);
  242. for (var i = 0, len = row.length; i < len; i++) {
  243. if (row[i].indexOf(this.quoteMark) !== -1) {
  244. row[i] = row[i].replace(this.quoteRegex, this.doubleQuoteMark);
  245. }
  246. if (row[i].indexOf(delimiter) !== -1 || row[i].indexOf(newline) !== -1) {
  247. row[i] = this.quoteMark + row[i] + this.quoteMark;
  248. }
  249. }
  250. return row.join(delimiter);
  251. },
  252. encodeArrays: function(coll: any, opts: any, fn: Function) {
  253. var delimiter = opts.delimiter;
  254. var newline = opts.newline;
  255. if (opts.header && this.getType(opts.header) === "Array") {
  256. fn(this.encodeCells(opts.header, delimiter, newline));
  257. }
  258. for (var cur = 0, lim = this.getLimit(opts.limit, coll.length); cur < lim; cur++) {
  259. fn(this.encodeCells(coll[cur], delimiter, newline));
  260. }
  261. return true;
  262. },
  263. encodeObjects: function (coll: any, opts: any, fn:Function) {
  264. var delimiter = opts.delimiter;
  265. var newline = opts.newline;
  266. var header;
  267. var row;
  268. header = [];
  269. row = [];
  270. for (var key in coll[0]) {
  271. header.push(key);
  272. row.push(coll[0][key]);
  273. }
  274. if (opts.header === true) {
  275. fn(this.encodeCells(header, delimiter, newline));
  276. } else if (this.getType(opts.header) === "Array") {
  277. fn(this.encodeCells(opts.header, delimiter, newline));
  278. }
  279. //@ts-ignore
  280. fn(this.encodeCells(row, delimiter));
  281. for (var cur = 1, lim = this.getLimit(opts.limit, coll.length); cur < lim; cur++) {
  282. row = [];
  283. for (var key$1 = 0, len = header.length; key$1 < len; key$1++) {
  284. row.push(coll[cur][header[key$1]]);
  285. }
  286. fn(this.encodeCells(row, delimiter, newline));
  287. }
  288. return true;
  289. },
  290. parse: function (text: any, opts: any, fn: Function) {
  291. var rows: any;
  292. if (this.getType(opts) === "Function") {
  293. fn = opts;
  294. opts = {};
  295. } else if (this.getType(fn) !== "Function") {
  296. rows = [];
  297. fn = rows.push.bind(rows);
  298. } else {
  299. rows = [];
  300. }
  301. //@ts-ignore
  302. opts = this.assign({}, this.STANDARD_DECODE_OPTS, opts);
  303. //@ts-ignore
  304. this.opts = opts;
  305. if (!opts.delimiter || !opts.newline) {
  306. var limit = Math.min(48, Math.floor(text.length / 20), text.length);
  307. opts.delimiter = opts.delimiter || this.mostFrequent(text, CELL_DELIMITERS, limit);
  308. opts.newline = opts.newline || this.mostFrequent(text, LINE_DELIMITERS, limit);
  309. }
  310. // modify by jl 由表自行控制不要含有双引号.提高解析效率
  311. return this.unsafeParse(text, opts, fn) &&
  312. (rows.length > 0 ? rows : true);
  313. },
  314. encode: function (coll: any, opts: any, fn: Function) {
  315. var lines: any;
  316. if (this.getType(opts) === "Function") {
  317. fn = opts;
  318. opts = {};
  319. } else if (this.getType(fn) !== "Function") {
  320. lines = [];
  321. fn = lines.push.bind(lines);
  322. }
  323. //@ts-ignore
  324. opts = this.assign({}, this.STANDARD_ENCODE_OPTS, opts);
  325. if (opts.skip > 0) {
  326. coll = coll.slice(opts.skip);
  327. }
  328. return (this.getType(coll[0]) === "Array" ? this.encodeArrays : this.encodeObjects)(coll, opts, fn) &&
  329. (lines.length > 0 ? lines.join(opts.newline) : true);
  330. }
  331. };
  332. @ccclass("csvManager")
  333. export class csvManager {
  334. /* class member could be defined like this */
  335. static _instance: csvManager;
  336. static get instance () {
  337. if (this._instance) {
  338. return this._instance;
  339. }
  340. this._instance = new csvManager();
  341. return this._instance;
  342. }
  343. private _csvTables:any = {};
  344. private _csvTableForArr:any = {};
  345. private _tableCast:any = {};
  346. private _tableComment:any = {};
  347. addTable (tableName:string, tableContent:string, force?:boolean) {
  348. if (this._csvTables[tableName] && !force) {
  349. return;
  350. }
  351. let tableData: any = {};
  352. let tableArr: any[] = [];
  353. let opts = { header: true,cast: "any"};
  354. CSV.parse(tableContent, opts, function (row: any, keyName: string) {
  355. tableData[row[keyName]] = row;
  356. tableArr.push(row);
  357. });
  358. this._tableCast[tableName] = (CSV as any).opts.cast;
  359. this._tableComment[tableName] = (CSV as any).opts.comment;
  360. this._csvTables[tableName] = tableData;
  361. this._csvTableForArr[tableName] = tableArr;
  362. //this.csvTables[tableName].initFromText(tableContent);
  363. }
  364. /**
  365. * 根据表名获取表的所有内容
  366. * @param {string} tableName 表名
  367. * @returns {object} 表内容
  368. */
  369. getTableArr (tableName:string) {
  370. return this._csvTableForArr[tableName];
  371. }
  372. /**
  373. * 根据表名获取表的所有内容
  374. * @param {string} tableName 表名
  375. * @returns {object} 表内容
  376. */
  377. getTable (tableName:string) {
  378. return this._csvTables[tableName];
  379. }
  380. /**
  381. * 查询一条表内容
  382. * @param {string} tableName 表名
  383. * @param {string} key 列名
  384. * @param {any} value 值
  385. * @returns {Object} 一条表内容
  386. */
  387. queryOne (tableName:string, key:string, value:any) {
  388. var table = this.getTable(tableName);
  389. if (!table) {
  390. return null;
  391. }
  392. if (key) {
  393. for (var tbItem in table) {
  394. if (!table.hasOwnProperty(tbItem)) {
  395. continue;
  396. }
  397. if (table[tbItem][key] === value) {
  398. return table[tbItem];
  399. }
  400. }
  401. } else {
  402. return table[value];
  403. }
  404. }
  405. /**
  406. * 根据ID查询一条表内容
  407. * @param {string}tableName 表名
  408. * @param {string}ID
  409. * @returns {Object} 一条表内容
  410. */
  411. queryByID (tableName:string, ID:string) {
  412. //@ts-ignore
  413. return this.queryOne(tableName, null, ID);
  414. }
  415. /**
  416. * 查询key和value对应的所有行内容
  417. * @param {string} tableName 表名
  418. * @param {string} key 列名
  419. * @param {any} value 值
  420. * @returns {Object}
  421. */
  422. queryAll (tableName:string, key:string, value:any) {
  423. var table = this.getTable(tableName);
  424. if (!table || !key) {
  425. return null;
  426. }
  427. var ret: any = {};
  428. for (var tbItem in table) {
  429. if (!table.hasOwnProperty(tbItem)) {
  430. continue;
  431. }
  432. if (table[tbItem][key] === value) {
  433. ret[tbItem] = table[tbItem];
  434. }
  435. }
  436. return ret;
  437. }
  438. /**
  439. * 选出指定表里所有 key 的值在 values 数组中的数据,返回 Object,key 为 ID
  440. * @param {string} tableName 表名
  441. * @param {string} key 列名
  442. * @param {Array}values 数值
  443. * @returns
  444. */
  445. queryIn (tableName:string, key:string, values:Array<any>) {
  446. var table = this.getTable(tableName);
  447. if (!table || !key) {
  448. return null;
  449. }
  450. var ret: any = {};
  451. var keys = Object.keys(table);
  452. var length = keys.length;
  453. for (var i = 0; i < length; i++) {
  454. var item = table[keys[i]];
  455. if (values.indexOf(item[key]) > -1) {
  456. ret[keys[i]] = item;
  457. }
  458. }
  459. return ret;
  460. }
  461. /**
  462. * 选出符合条件的数据。condition key 为表格的key,value 为值的数组。返回的object,key 为数据在表格的ID,value为具体数据
  463. * @param {string} tableName 表名
  464. * @param {any} condition 筛选条件
  465. * @returns
  466. */
  467. queryByCondition (tableName:string, condition: any) {
  468. if (condition.constructor !== Object) {
  469. return null;
  470. }
  471. var table = this.getTable(tableName);
  472. if (!table) {
  473. return null;
  474. }
  475. var ret: any = {};
  476. var tableKeys = Object.keys(table);
  477. var tableKeysLength = tableKeys.length;
  478. var keys = Object.keys(condition);
  479. var keysLength = keys.length;
  480. for (var i = 0; i < tableKeysLength; i++) {
  481. var item = table[tableKeys[i]];
  482. var fit = true;
  483. for (var j = 0; j < keysLength; j++) {
  484. var key = keys[j];
  485. fit = fit && (condition[key] === item[key]) && !ret[tableKeys[i]];
  486. }
  487. if (fit) {
  488. ret[tableKeys[i]] = item;
  489. }
  490. }
  491. return ret;
  492. }
  493. queryOneByCondition (tableName:string, condition: any) {
  494. if (condition.constructor !== Object) {
  495. return null;
  496. }
  497. var table = this.getTable(tableName);
  498. if (!table) {
  499. return null;
  500. }
  501. var keys = Object.keys(condition);
  502. var keysLength = keys.length;
  503. for (let keyName in table) {
  504. var item = table[keyName];
  505. var fit = true;
  506. for (var j = 0; j < keysLength; j++) {
  507. var key = keys[j];
  508. fit = fit && (condition[key] === item[key]);
  509. }
  510. if (fit) {
  511. return item;
  512. }
  513. }
  514. return null;
  515. }
  516. }