CSV解析器,CSV解释器,新媒传信上机题,新媒传信面试,java解析csv

原题:



更复杂点的CSV文本:

"o""reily","""orange,lime""",2008-09-01,",,nil""""",1980-e09


循环解题:

	public static void parseCsv(String sourceLine) {
		if (null == sourceLine) {
			System.err.println("Source text is null!");
			return;
		}
		String[] cells = sourceLine.split(",");
		for (int i = 0; i < cells.length; i++) {
			// 确保没有null的字符串
			String cell = cells[i];
			if (null == cell) {
				cell = "";
			}

			// 计算“"”个数
			int len = cell.length();
			int num = 0;
			for (int j = 0; j < len; j++) {
				if (cell.charAt(j) == '\"') {
					num++;
				}
			}

			// 如果“"”个数为偶数,则CSV字段完整,否则CSV字段不完整
			if (num % 2 == 0) {
				// 删除首尾的“"”
				if (cell.startsWith("\"") && cell.endsWith("\"") && cell.length() > 1) {
					cell = cell.substring(1, cell.length() - 1);
				}
				cell = cell.replaceAll("\"\"", "\"");
				System.out.println(cell);
			} else {
				// cell不完整,并且是最后一个cell,则非法的csv格式
				if (i == cells.length - 1) {
					System.err.println("Illegal csv text!");
					return;
				}
				// 将不完整的cell拼接到下一个cell
				int nextIndex = i + 1;
				cells[nextIndex] = cells[i] + "," + cells[nextIndex];
			}
		}
	}

递归解题:

	public static void parseCsvRecursively(String sourceLine) {
		if (sourceLine == null) {
			System.err.println("Source text is null!");
			return;
		}
		if (sourceLine.contains(",")) {
			// 包含“,”,遍历所有字符
			StringBuilder sourceBuf = new StringBuilder(sourceLine);
			int length = sourceBuf.length();
			// 双引号个数
			int doubleQuotesCount = 0;

			for (int i = 0; i < length; i++) {
				char c = sourceBuf.charAt(i);
				if (c == '\"') {
					doubleQuotesCount++;
				} else if (c == ',') {
					// 双引号个数为偶数,表示截止索引i之前的字符串为完整CSV字段,循环结束
					if (doubleQuotesCount % 2 == 0) {
						// 解析打印i之前的完整CSV字段
						parseAndPrintCell(sourceBuf.substring(0, i));

						// 如果i后面还有字符串,递归处理余下的CSV字符串
						if (i < length - 1) {
							parseCsvRecursively(sourceBuf.substring(i + 1));
						}
						break;
					}
				}
			}
		} else {
			// 不包含“,”,一个独立的CSV字段
			parseAndPrintCell(sourceLine);
		}
	}

	private static void parseAndPrintCell(String cell) {
		if (cell == null) {
			return;
		}
		StringBuilder cellBuf = new StringBuilder(cell);
		// 删除首尾“"”
		if (cellBuf.length() > 1 && cellBuf.charAt(0) == '\"' && cellBuf.charAt(cellBuf.length() - 1) == '\"') {
			cellBuf.deleteCharAt(cellBuf.length() - 1);
			cellBuf.deleteCharAt(0);
		}
		// 两个双引号替换成一个
		int twoQuotesIndex, // 双引号的位置
			fromIndex = 0;// 查找双引号的起始位置
		while ((twoQuotesIndex = cellBuf.indexOf("\"\"", fromIndex)) > -1) {
			// 两个双引号,删除一个
			cellBuf.deleteCharAt(twoQuotesIndex);
			
			// 下次循环,从当前双引号的后面位置开始查找
			fromIndex = twoQuotesIndex + 1;
			// 如果位置超出字符串,停止循环
			if (fromIndex >= cellBuf.length()) {
				break;
			}
		}
		System.out.println(cellBuf);
	}


比较高效的解法:

	public static void parseCsv(String sourceLine) {
		if (null == sourceLine) {
			System.err.println("Source text is null!");
			return;
		}
		
		StringBuilder sourceBuf = new StringBuilder(sourceLine);
		StringBuilder cellBuf = new StringBuilder();
		int length = sourceBuf.length();
		int dubbleQuotesCount = 0;

		for (int i = 0; i < length; i++) {
			char c = sourceBuf.charAt(i);
			if (c == ',') {
				// 如果双引号个数为偶数,则CSV字段完整,否则CSV字段不完整
				if (dubbleQuotesCount % 2 == 0) {
					parseAndPrintCell(cellBuf);
					cellBuf.setLength(0);
				} else {
					cellBuf.append(c);
				}
			} else {
				// 双引号计数
				if (c == '\"') {
					dubbleQuotesCount++;
				}
				
				// 除了逗号,其他字符全部放入CellBuffer
				cellBuf.append(c);
				
				// 处理最后一个不是以逗号结尾CSV字段
				if (i >= length - 1) {
					if (dubbleQuotesCount % 2 == 0) {
						parseAndPrintCell(cellBuf);
						cellBuf.setLength(0);
					} else {
						System.err.println("Illegal csv text!");
					}
				}
			}
		}
	}

	private static void parseAndPrintCell(StringBuilder cellBuf) {
		// 删除首尾“"”
		if (cellBuf.length() > 1 && cellBuf.charAt(0) == '\"' && cellBuf.charAt(cellBuf.length() - 1) == '\"') {
			cellBuf.deleteCharAt(cellBuf.length() - 1);
			cellBuf.deleteCharAt(0);
		}
		// 两个双引号替换成一个
		int twoQuotesIndex, // 双引号的位置
			fromIndex = 0;// 查找双引号的起始位置
		while ((twoQuotesIndex = cellBuf.indexOf("\"\"", fromIndex)) > -1) {
			// 两个双引号,删除一个
			cellBuf.deleteCharAt(twoQuotesIndex);
			
			// 下次循环,从当前双引号的后面位置开始查找
			fromIndex = twoQuotesIndex + 1;
			// 如果位置超出字符串,停止循环
			if (fromIndex >= cellBuf.length()) {
				break;
			}
		}
		System.out.println(cellBuf);
	}


正则解题:

百度搜“CSV解析器”,答案很多。



  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值