CsvParser.ts 18 KB

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