原因描述

在配置Maven工程的基本工作单元POM的过程中,因为代理问题,所以我就把一些配置直接复制粘贴到setting.xml上了。但是在这个文件被读取解析过程中,一些空格、换行符被解析为text文本,导致xml配置文件解析错误。错误信息如下:

[ERROR] Error executing Maven.
 [ERROR] 1 problem was encountered while building the effective settings
 [FATAL] Non-parseable settings C:\Users\user.m2\settings.xml: expected START_TAG or END_TAG not TEXT (position: TEXT seen …\n\ua0\ua0\ua0 \n\ua0\ua0\ua0 -->\n\ua0\ua0\ua0\ua0 <m… @182:8) @ C:\Users\user.m2\settings.xml, line 182, column 8

这个问题的原因我猜测是因为Maven在用JAXP解析该XML文件时,用了SAX解析器,但是没处理好前后空格和换行符,这是一个细微的BUG,或许之后的版本会改好。所以它的处理方式也很简单,就是你找到报错所在的行,删除标签前后的空格或者换行符就好,之后就能通过了。
其实SAX解析中,有个很好去除空格的方法就是利用 trim() 函数,利用代码:

if(!value.trim().equals("")){//如果value去掉空格后不是空字符串
	System.out.println("节点值是:" + value);
}

这样可以很好的避免把XML文件中标签前后的空格、换行符解析出来。

联想

如何将一段代码或者文本中的空格(/s)、制表符(/t)、回车(/n)和换行符(/r) 删除,让其成为一整段代码?

Tips:关于“回车”(carriage return)和“换行”(line feed)这两个概念的来历和区别。
在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。
于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界;另一个叫做“换行”,告诉打字机把纸向下移一行。
这就是“换行”和“回车”的来历,从它们的英语名字上也可以看出一二。
后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。
Unix 系统里,每行结尾只有“<换行>”,即“\n”;Windows系统里面,每行结尾是“ <回车><换 行>”,即“\r\n”;Mac系统里,每行结尾是“<回车>”。一个直接后果是,Unix/Mac系统下的文件在Windows里打 开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。

下面我写了一段代码就是用来删除TXT文本中的空白符号和空行的。

/*
1. 输入文件夹,循环该文件夹下所有TXT文件,删除文件中的空白字符和空行。
2. 直接利用main函数参数来输入文件夹路径。
*/
import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class Replace {

	public static void main(String[] args) {	//直接利用main函数参数输入文件夹路径
		Replace r = new Replace();
		r.removeSpaceAndLinebreak(args[0]);
	}

	public void removeSpaceAndLinebreak(String url){

		try{
			File srcFile = new File(url);
			boolean b = srcFile.exists();
			if (b && srcFile.isDirectory()) {	//判断是否是路径是否存在,是否是文件夹
				File[] file = srcFile.listFiles();
				if (file.length == 0) {
						System.out.println("文件夹内不存在文件!");
						System.exit(0);
				};
				for (int i = 0; i < file.length; i++) {
					//file[i]就是循环出来的文件夹里的文件。然后用下面的方法读它。
					if (!file[i].getName().endsWith("txt")) {	//判断是否是TXT文件
						System.out.println(file[i].getName()+"不是TXT文件!");
						continue;
					}
					Runtime.getRuntime().exec("notepad "+file[i].getAbsolutePath());//打开待处理文件,参数是字符串,是个命令
					String str = null;
					String REGEX = "\\s+";	//空格、制表符正则表达式,\s匹配任何空白字符,包括空格、制表符、换页符等

					InputStreamReader stream = new InputStreamReader(new FileInputStream(file[i]),"UTF-8");	//读入字节流,并且设置编码为UTF-8																
					BufferedReader reader = new BufferedReader(stream);	构造一个字符流的缓存器,存放在控制台输入的字节转换后成的字符

					File newFile = new File(file[i].getParent(),"new"+file[i].getName());	//建立将要输出的文件和文件名

					OutputStreamWriter outstream = new OutputStreamWriter(new FileOutputStream(newFile),"UTF-8");	//写入字节流
					BufferedWriter writer = new BufferedWriter(outstream);
					Pattern patt = Pattern.compile(REGEX);	//创建Pattern对象,处理正则表达式
					
					while ((str = reader.readLine()) != null) {	
						Matcher mat = patt.matcher(str);	//先处理每一行的空白字符
						str = mat.replaceAll("");

						if (str == "") {	//如果不想保留换行符直接写入就好,不用多此一举
							continue;
						}else{
							writer.write(str);	//如果想保留换行符,可以利用str+"\r\n" 来在末尾写入换行符
						}
					}
					writer.close();
					reader.close();

					//打开修改后的文档
					Runtime.getRuntime().exec("notepad "+newFile.getAbsolutePath());	
				}
				System.out.println("文件修改完成!");
			}else{
				System.out.println("文件夹路径不存在或输入的不是文件夹路径!");
				System.exit(0);
			}
		}
		catch(IOException e){
			System.out.println(e);
		}
	}
}