原因描述
在配置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);
}
}
}