JAVA对特殊字符的处理

最近在维护OA系统的时候,刚好遇到几个类似的问题。总结了一下大概是下面三种情况。

1.在拼接原生SQL的时候,特殊字符如【'】,破坏了SQL的完整性。

public String escapeExprSpecialWord(String keyword) {  
	    if (StringUtils.isNotEmpty(keyword)) {  
	        String[] fbsArr = { "\\","$","(",")","*","+",".","[", "]","?","^","{","}","|","'","%" };  
	        for (String key : fbsArr) {  
	            if (keyword.contains(key)) {  
	                keyword = keyword.replace(key, "\\" + key);  
	            }  
	        }  
	    }  
	    return keyword;  
	}

2.返给前端json数据,com.alibaba.fastjson.JSONObject.toJSONString(),如果内容中包含特殊字符\n,\t,\r等,会导致前端json无法正常解析。

public String formatJsonStr(String str){
		if(StringUtils.isNotEmpty(str)){
			String[] formatStrs = {"\t","\r","\n"};
			for(String key:formatStrs){
				if(str.contains(key)){
					str = str.replace(key, ",");
				}
			}
		}
		return str;
	}

3.文件上传及下载,文件名中有【,】也会导致无法下载,或下载内容为空。

/**
	 * 上传文件
	 * @param files
	 * @return
	 */
	public List<AttachmentEntity> upload(File[] files, String[] fileNames) {
		List<AttachmentEntity> list = new ArrayList<AttachmentEntity>();
		Properties prop = new Properties();
		FileInputStream fis =null;
		InputStream in  = null;
		InputStream propertiesIn  = null;
		FileOutputStream out = null ;
		
		try {
			Resource[] resources = RESOLVER
					.getResources("classpath*:com/**/**/META-INF/upload/*.conf");
			if (resources == null || resources.length < 1) {
				LOGGER.error("上传文件失败,失败原因 : ", "client.conf不存在!");
				return list;
			} else {

				in = resources[0].getInputStream();
				File file = new File("client.conf");
				out = new FileOutputStream(file);
				byte[] buf = new byte[1024];
				while (true) {
					int r = in.read(buf);
					if (r == -1) {
						break;
					}
					out.write(buf, 0, r);
				}

				ClientGlobal.init(file.getAbsolutePath());
				LOGGER.info("上传中:" + "客户端配置文件初始化完成 ");
				// getting connection of FastDFS
				TrackerClient trackerClient = new TrackerClient();
				TrackerServer trackerServer = trackerClient.getConnection();
				if (trackerServer != null) {
					LOGGER.info("上传中:" + "均衡器初始化成功");
				}
				StorageServer storageServer = null;
				StorageClient storageClient = new StorageClient(trackerServer,
						storageServer);
				propertiesIn = new FileInputStream(file.getAbsolutePath());
				prop.load(propertiesIn);
				String iP = trackerServer.getInetSocketAddress().getHostName();//获取fastdfs IP
				String  ipAndPort = iP+":"+prop.getProperty("http.tracker_server_port");//获取fastdfs 对应下载http uri(ip+端口)
				String fileExtName = "";
				for (int i = 0; i < files.length; i++) {
					
					AttachmentEntity entity = new AttachmentEntity();
					entity.setId(UUIDUtil.generate());
					entity.setAttachmentName(fileNames[i]);//这里fileName中,包含特殊符号,比如逗号,在更新到数据库中没有变化
					entity.setActive("Y");
					entity.setIpAndPort(ipAndPort);//为附件添加http uri;
					if (fileNames[i].contains(".")) {
						fileExtName = fileNames[i].substring(fileNames[i]
								.lastIndexOf(".") + 1);
					} else {
						LOGGER.error("上传文件失败,失败原因 : ", "文件名非法");
					}
					 fis = new FileInputStream(files[i]);
					byte[] file_buff = null;
					if (fis != null) {
						int len = fis.available();
						file_buff = new byte[len];
						fis.read(file_buff);
					}
					LOGGER.info("file length: " + file_buff.length);
					// meta data setting  fileNameString(fileNames[i])
					NameValuePair[] meta_list = new NameValuePair[3];
					meta_list[0] = new NameValuePair("fileName", fileNameString(fileNames[i]));//这里将fileNameString(fileNames[i])将原来文件名中逗号替换为空格
					meta_list[1] = new NameValuePair("fileExtName", fileExtName);
					meta_list[2] = new NameValuePair("fileLength",
							String.valueOf(files[i].length()));
					String group_name = null;
					// get store storages
					StorageServer[] storageServers = trackerClient
							.getStoreStorages(trackerServer, group_name);
					if (storageServers == null) {
						LOGGER.error("访问存储服务器失败,失败原因 : ",
								storageClient.getErrorCode());
					} else {
						LOGGER.info("store 数目: " + storageServers.length);
						for (int k = 0; k < storageServers.length; k++) {
							LOGGER.info(k
									+ 1
									+ ". "
									+ storageServers[k].getInetSocketAddress()
											.getAddress().getHostAddress()
									+ ":"
									+ storageServers[k].getInetSocketAddress()
											.getPort());
						}
					}

					long startTime = System.currentTimeMillis();
					// upload files
					String[] results = storageClient.upload_file(file_buff,
							fileExtName, meta_list);
					LOGGER.info("已上传至服务器,用时 : ",
							(System.currentTimeMillis() - startTime) + " ms");
					if (results == null) {
						LOGGER.error("上传文件 失败,error code: "
								+ storageClient.getErrorCode());
					}

					// // get groupName and remoteFileName
					group_name = results[0];
					String remote_filename = results[1];
					LOGGER.info("group_name: " + group_name
							+ ", remote_filename: " + remote_filename);
					LOGGER.info(storageClient.get_file_info(group_name,
							remote_filename).toString());
					entity.setPosition(group_name + "/" + remote_filename);
					
					// get storage sever of this file
					ServerInfo[] servers = trackerClient.getFetchStorages(
							trackerServer, group_name, remote_filename);
					if (servers == null) {
						LOGGER.error("获取tracker失败, error code: "
								+ trackerClient.getErrorCode());
					} else {
						LOGGER.info("storage 数目: " + servers.length);
						for (int k = 0; k < servers.length; k++) {
							System.err.println(k + 1 + ". "
									+ servers[k].getIpAddr() + ":"
									+ servers[k].getPort());
						}
					}
					attachmentDao.add(entity);
					LOGGER.info("附件信息成功插入数据库");
					list.add(entity);
				
				}
				return list;
			}
		} catch (FileNotFoundException fnfex) {
			LOGGER.error("文件未找到:" + fnfex.getMessage());
			return list;
		} catch (IOException ioe) {
			LOGGER.error("IO错误:" + ioe.getMessage());
			return list;
		} catch (MyException mye) {
			LOGGER.error("FastDFS错误 :" + mye.getMessage());
			return list;
		} catch (Exception e) {
			LOGGER.error("其他错误 :" + e.getMessage());
			return list;
		}
		finally{
			try {
				fis.close();
				in.close();
				propertiesIn.close();
				out.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
/**
	 * 文件下载
	 * @param id
	 * @param fileName
	 */
	@Override
	public void download(String id, String fileName) {
		InputStream in= null;
		FileOutputStream out  = null;
		try {
			Resource[] resources = RESOLVER
					.getResources("classpath*:com/**/**/META-INF/upload/*.conf");
			if (resources == null || resources.length < 1) {
				LOGGER.error("下载文件失败,失败原因 : ", "client.conf不存在!");
			} else {

				 in = resources[0].getInputStream();
				File file = new File("client.conf");
				 out = new FileOutputStream(file);
				byte[] buf = new byte[1024];
				while (true) {
					int r = in.read(buf);
					if (r == -1) {
						break;
					}
					out.write(buf, 0, r);
				}

				LOGGER.info("fileName:" + fileName);
				ClientGlobal.init(file.getAbsolutePath());
				LOGGER.info("下载中:" + "client.conf初始化成功!");
				TrackerClient trackerClient = new TrackerClient();
				TrackerServer trackerServer = trackerClient.getConnection();
				if (trackerServer != null) {
					LOGGER.info("下载中:" + "成功获得均衡器");
				} else {
					LOGGER.error("下载失败:" + "均衡器获取失败");
				}
				StorageServer storageServer = null;

				StorageClient storageClient = new StorageClient(trackerServer,
						storageServer);
				// groupName and remoteFileName should exist
				String group_name = "group1";
				AttachmentEntity aEntity = attachmentDao.queryById(id);
				String remote_filename = aEntity.getPosition();
				String[] paths = remote_filename.split("/");
				FileInfo fi = storageClient.get_file_info(paths[0],
						remote_filename.replace(paths[0] + "/", ""));
				LOGGER.error("下载中..." + "得到文件信息");
				HttpServletResponse response = ResponseContext
						.geRequestContext().getResponse();
				response.reset();
				response.setContentType("application/download;charset=UTF-8");
				// response.setHeader("Content-Disposition","attachment;" +
				// "filename=" + new String(fileName.getBytes("ISO_8859_1"),
				// "UTF-8"));
				// 如果使用上面编码格式,否则附件名称若为中文,则乱码,下载下来的附件名称,显示不全.或者乱乱码 .应该使用下面的编码格式.
				LOGGER.info("fileName(gbk)=[" + new String(fileNameString(fileName).getBytes("gbk"), "ISO8859-1") +"]");
				response.setHeader("Content-Disposition", "attachment;"
						+ "filename="
						+ new String(fileNameString(fileName).getBytes("gbk"), "ISO8859-1"));//无法下载,原因可能是在这里文件名中有逗号,在解析header的时候,逗号导致。这里请求文件名,应该与写入的保持一致
				// String basepath =
				// System.getProperties().getProperty("user.home");
				// String path = basepath + File.separator + new
				// String(fileName.getBytes("GBK"), "ISO_8859_1");
				ServletOutputStream oOutput = response.getOutputStream();
				byte[] inputStream = storageClient.download_file(paths[0],
						remote_filename.replace(paths[0] + "/", ""));
				try {
					oOutput.write(inputStream);
					oOutput.flush();
				} catch (IOException ioe) {
					LOGGER.error("下载失败:" + "写入本地文件失败!");
				} finally {
					IOUtils.close(oOutput);
				}

				String sourceIpAddr = fi.getSourceIpAddr();
				long size = fi.getFileSize();
				LOGGER.info("ip:" + sourceIpAddr + ",size:" + size);
			}
		} catch (FileNotFoundException fnfex) {
			LOGGER.error("下载失败,文件未找到:" + fnfex.getMessage());
		} catch (IOException ioex) {
			LOGGER.error("下载失败,IO 错误 :" + ioex.getMessage());
		} catch (MyException e) {
			LOGGER.error("下载失败,其他错误 :" + e.getMessage());
		}
		finally {
			 try {
				 if(in!=null)
				in.close();
				 if(out!=null)
				 out.close(); 
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}	
			
		}
	}
public String fileNameString(String fileName){
        if(fileName.contains(",")){
        	fileName = fileName.replace(","," ");
        }
        return fileName;
    }

这三个问题,本质都是特殊字符导致的错误。这里提供后台的处理方式,供大家参考

<think>嗯,用户问的是Java特殊字符的转义处理。首先,我得确认用户的基础,可能是个刚开始学Java的人,或者在处理字符串时遇到了问题。需要先解释什么是转义字符,然后列举常见的例子,比如引号、反斜杠、换行符这些。 接着,要说明Java中转义的方式,主要是用反斜杠。比如如何输出双引号,或者处理文件路径中的反斜杠。用户可能会混淆不同场景下的转义,比如正则表达式和Java本身的转义规则,需要特别指出两者的区别,提醒注意。 然后,可能需要提到在正则表达式中需要双重转义的情况,比如匹配一个数字\d,在Java中要写成\\d。还有StringEscapeUtils这样的工具,方便处理HTML、XML等格式的转义,但需要引入Apache Commons库,这点要说明清楚。 用户可能的问题场景包括:处理文件路径时出错,字符串中包含特殊符号导致编译错误,或者在正则表达式中没有正确转义。需要给出具体的例子,比如文件路径的正确写法,或者如何输出带换行的字符串。 另外,可能需要提醒用户注意不同上下文中的转义规则变化,比如在正则表达式和普通字符串中的不同处理方式。还有Unicode转义的情况,虽然不太常用,但可以作为补充知识。 最后,总结一下关键点,强调正确使用转义的重要性,避免常见的错误。可能还需要检查是否有遗漏的特殊字符,比如退格符、制表符等,确保覆盖全面。</think>Java特殊字符的转义处理主要涉及以下场景和规则: --- ### 一、什么是转义字符? 在 Java 中,某些字符具有特殊含义(如 `"`, `\`, `\n` 等),如果直接写入字符串或字符字面量,编译器会将其解释为特殊操作。需要通过**反斜杠 `\`** 进行转义,将其转换为普通字符。 --- ### 二、常见转义字符列表 | 转义序列 | 含义 | 示例代码 | 输出结果 | |----------|------------------------|------------------------------|-------------------| | `\"` | 双引号 | `System.out.println("Hello\"World");` | `Hello"World` | | `\'` | 单引号 | `char c = '\'';` | 字符 `'` | | `\\` | 反斜杠 | `String path = "C:\\Users\\";` | `C:\Users\` | | `\n` | 换行符 | `System.out.print("A\nB");` | 输出两行 `A` 和 `B` | | `\t` | 制表符 | `System.out.print("Name\tAge");` | `Name Age` | | `\r` | 回车符 | `System.out.print("Hello\rWorld");` | 覆盖输出 `World` | | `\b` | 退格符 | `System.out.print("A\bB");` | `B`(覆盖 `A`) | | `\f` | 换页符(极少使用) | - | - | --- ### 三、关键应用场景 #### 1. 字符串中的引号 ```java // 错误写法:字符串中的双引号会提前结束字符串 // String s = "He said "Hello""; // 正确转义 String s = "He said \"Hello\""; ``` #### 2. 文件路径处理 ```java // 错误写法:单反斜杠会被解释为转义符 // String path = "C:\Users\test.txt"; // 正确转义 String path = "C:\\Users\\test.txt"; ``` #### 3. 正则表达式中的转义 正则表达式中的特殊字符(如 `.`, `*`, `\d` 等)需要**双重转义**: ```java // 匹配数字 \d,需写成 \\\\d String regex = "\\d+"; // 实际正则表达式为 \d+ ``` --- ### 四、高级转义工具 对于复杂场景(如 HTML/XML/JSON),可使用工具: ```java import org.apache.commons.text.StringEscapeUtils; // HTML 转义 String escapedHtml = StringEscapeUtils.escapeHtml4("<div>Hello</div>"); // 输出 <div>Hello</div> ``` --- ### 五、注意事项 1. **Unicode 转义**:`\uXXXX` 形式(如 `\u0041` 表示 `A`),但需注意编译顺序。 2. **原始字符串(Java 15+)**:使用三引号避免转义: ```java String json = """ {"name": "John", "age": 30}"""; ``` --- ### 总结 Java 通过反斜杠 `\` 对特殊字符进行转义,需注意不同上下文(字符串、正则、文件路径)的转义规则差异。合理使用转义能避免语法错误和逻辑异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值