需求是这样的,有些url有特殊字符,而这些特殊字符在windows的文件名里是不能拥有的,所以要把这样特殊字符都替换成别的字符
比如
3g.qq.com:80\forward.jsp
本地的文件名就是
3g.qq.com:80_forward.jsp也就说给我的参数是3g.qq.com:80\forward.jsp,而我要转为3g.qq.com:80_forward.jsp代码:String str = "3g.qq.com:80\forward.jsp";
System.out.println(str.replaceAll("\\", "_"));
报错Exception in thread "main" java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
\
 ^
at java.util.regex.Pattern.error(Pattern.java:1713)
at java.util.regex.Pattern.compile(Pattern.java:1466)
at java.util.regex.Pattern.<init>(Pattern.java:1133)
at java.util.regex.Pattern.compile(Pattern.java:823)
at java.lang.String.replaceAll(String.java:2190)
at com.lmiky.test.StringTest.main(StringTest.java:46)
我知道\f, \t等是转义符,我也知道正确的应该是\\,但是我现在能得到的就是\,不知道有什么办法实现

解决方案 »

  1.   

    代码又错鸟...String str = "3g.qq.com:80\forward.jsp";
    System.out.println(str);结果:3g.qq.com:80 orward.jsp
    String str = "3g.qq.com:80\\forward.jsp";
    System.out.println(str);
    System.out.println(str.replaceAll("\\\\", "_"));
      

  2.   

    public static void replaceStr(){
    String str="3g.qq.com:80\forward.jsp";
    Pattern p = Pattern.compile("\\t");
    Matcher m = p.matcher(str);
    if (m.find()){
    str = m.replaceAll("_\\t");
    }
    System.out.println(str);
    }
      

  3.   

    一,你定义的常量就是错的。你的常量内容是3g.qq.com:80\forward.jsp在java里它就必须这么写 
    String str = "3g.qq.com:80\\forward.jsp";
    你在str下面打印一下str就知道是怎么回事了二,下面的str.replaceAll("\\\\", "_")对了,它首先进行java的转译,代表你要把正则表达式\\(也就是字符\) 换成 _   之所以\在正则里需要用\\表示\是因为正则也需要转译。
      

  4.   

    String str = "3g.qq.com:80\forward.jsp";
    System.out.println(str.replaceAll("\f", "_f").replaceAll("\\\\", "_"));
      

  5.   


    String str = "3g.qq.com:80\forward.jsp";
    System.out.println(str.replace("\f", "_f"));
      

  6.   

    ....
    我很无语啊...
    传给你的字符串,你看到的是3g.qq.com:80\forward.jsp
    实际存储的是3g.qq.com:80\\forward.jsp懂?
      

  7.   

    是这样的
    这个3g.qq.com:80\forward.jsp是从数据库读取出来的,而我要转为3g.qq.com:80_forward.jsp,然后在本地找名字为3g.qq.com:80_forward.jsp的文件,然后读这个文件里的数据
      

  8.   

    那只是个例子,实际3g.qq.com:80\forward.jsp是我从数据库里读取出来的
      

  9.   

    不管你的数据哪里取出来的
    只要你Syste.out.print出来看到是3g.qq.com:80\forward.jsp这样
    他的实际存储就是 \\ 两个啊两个....
      

  10.   


    9楼之前谁知道是从数据库里去出来的?
    那System.out.println(str.replaceAll("\\\\", "_"));就一点都没错。
    你连上数据库去测试就完事了。
      

  11.   

    直接用replaceAll("\\\\","_")就行了哈:public class Test14 {
    public static void main(String[] args) {
    String url = "3g.qq.com:80\\tab\\back\\forward.jsp"; url = url.replaceAll("\\\\", "_"); System.out.println("Result:" + url);
    }
    }
    如果实在绕不过弯来就干脆别用replaceAll改用replace就好了嘛:public class Test14 {
    public static void main(String[] args) {
    String url = "3g.qq.com:80\\tab\\back\\forward.jsp"; while (url.contains("\\"))
    url = url.replace('\\', '_'); System.out.println("Result:" + url);
    }
    }
      

  12.   

    LZ  花了两个帖子。都没把大家弄清楚哈哈。。 我爱莫能助我的办法也是 。。把所有可能出现的转义字符 做处理。。再替换但太麻烦。。估计有简单的  函数可以实现我也像看看答案。。哈哈。。
    LZ  继续解释你的问题。哈哈。。
      

  13.   

    但是他打印出来的不是3g.qq.com:80\forward.jsp,我之所以知道是3g.qq.com:80\forward.jsp,是因为我看到数据库里面存储的值是3g.qq.com:80\forward.jsp
    这个真的不是一个\或\\的问题,我想问的是一个\的话,要怎么替换
      

  14.   

    首先一楼的解决方案是完全正确的,要使用4个“\”,为什么要使用4个呢。
    我来解释一下吧。\\ 前面2个在Java中表示一个“\”。
    在使用正则表达式替换一个"\"的时候为什么要使用4个呢。
    因为“\”在正则表达式中也是一个“特殊字符”同样是需要被转义的,所以在Java中输出2个“\\”在正则表达式中才能表示为一个“\”。
    楼主可以查看一下JDK API DOC文档。我下面贴一点官方的说明。-------------------------------------------------------------------------------------
    public final class Pattern extends Object implements Serializable正则表达式的编译表示形式。 指定为字符串的正则表达式必须首先被编译为此类的实例。然后,可将得到的模式用于创建 Matcher 对象,依照正则表达式,该对象可以与任意字符序列匹配。执行匹配所涉及的所有状态都驻留在匹配器中,所以多个匹配器可以共享同一模式。 因此,典型的调用顺序是  Pattern p = Pattern.compile("a*b");
     Matcher m = p.matcher("aaaaab");
     boolean b = m.matches();在仅使用一次正则表达式时,可以方便地通过此类定义 matches 方法。此方法编译表达式并在单个调用中将输入序列与其匹配。语句  boolean b = Pattern.matches("a*b", "aaaaab");等效于上面的三个语句,尽管对于重复的匹配而言它效率不高,因为它不允许重用已编译的模式。 
    此类的实例是不可变的,可供多个并发线程安全使用。Matcher 类的实例用于此目的则不安全。 正则表达式的构造摘要 
    构造 匹配 
      
    字符 
    x 字符 x 
    \\ 反斜线字符 没有贴全,楼主还是自己去查询API吧。
      

  15.   

     各位同学请看大屏幕:
     假如字符串是:String str = "3g.qq.com:80\forward.jsp";
    那么我们直接用System.out.println(str.replaceAll("\\\\", "_"));
    是不行的..  接着往下看:我们在前面的字符串加一个"\"
    String str = "3g.qq.c\om:80\forward.jsp";
    比如这样.
    但是编辑器会报错,为什么呢,因为字符串中"\"是不能存在的,只能这样
    String str = "3g.qq.c\\om:80\forward.jsp";
     见证奇迹的时候到了: 
    什么这个能存在呢 String str = "3g.qq.com:80\forward.jsp";
    因为系统没把这个字符中的"\" 当成"\",而是和"\f"同时存在的,所以系统不会报错.问题的根结找到了....
    下面解决:根结这个根结:那么所有的字符串中的"\" 都不是作为"\"存在的
      

  16.   

    str = "\test";看下这个字符串的长度是多少
    str = "\\test";再看下这个字符串的长度是多少然后再看下从数据库中读取出来的数据的长度是多少
    然后再看下不从数据库中读取,而直接赋值的字符串的长度是多少或者把他们当成字符数据,一个一个的元素看他们的ascii码是多少
      

  17.   

     如果字符串未知并且海量的话..  小弟才疏学浅..能想到的办法是,把所有的转义字符做成数据字典,然后根据字段先改正"\"(后面跟的字母组合"\*"肯定是转义字符) ..通过匹配把 "\" 改成"\\*" .这样计算机就不会犯错误了 ..然后
    str.replaceAll("\\\\", "_")..OK  各位还有什么更好的办法,畅所欲言.. 互相学习
      

  18.   

      楼主 , 你可以先在 数据库里做处理 : replaceAll("\","\\")
      

  19.   


    public static void main(String[] args) {
    String input = "3g.qq.com:80\\forward.jsp"; Pattern p = Pattern.compile("\\\\");
    Matcher m = p.matcher(input);
    String r = m.replaceAll("_");
    System.out.println(r); Pattern p2 = Pattern.compile("\\", Pattern.LITERAL);
    Matcher m2 = p2.matcher(input);
    String r2 = m2.replaceAll("_");
    System.out.println(r2);
    }
    为了解决楼主的疑惑,我上面做了一个例子,楼主可以看一下。
    第一个例子与第二个例子区别是在于第二个例子启动了LITERAL模式。API描述:LITERAL
    public static final int LITERAL启用模式的字面值解析。 
    指定此标志后,指定模式的输入字符串就会作为字面值字符序列来对待。输入序列中的元字符或转义序列不具有任何特殊意义。 标志 CASE_INSENSITIVE 和 UNICODE_CASE 在与此标志一起使用时将对匹配产生影响。其他标志都变得多余了。 不存在可以启用字面值解析的嵌入式标志字符。 
    从以下版本开始: 
    1.5 
    另请参见:
    常量字段值------------------------------------------------------------------------------
    因为启动LITERAL模式之后,特殊字符将不具有特殊的意义,当作一个普通的文档对待。
    所以第二个例子即使使用2个“\”也能够正确的替换。而默认LITERAL是不启动的,所以第一个例子还是使用4个"\"替换。
      

  20.   


    String str = "3g.qq.com:80\forward.jsp";
    System.out.println(str.replaceAll("\\", "_"));String str = "3g.qq.com:80\\forward.jsp";
    System.out.println(str.replaceAll("\\", "_"));
    在补充一下,我认为楼主的认识是有误区的。
    第一个例子显然不正确的,因为没有“\”所以无法替换。我打一个简单的比方:
    页面上面有一个输入框用户输入了“\”他只是想要输入一个“\”,但是这个时候你难道要要求他输入2个“\”来表示1个“\”吗?
    public static void main(String[] args) {
    Scanner s = new Scanner(System.in);

    //String input = "3g.qq.com:80\\forward.jsp";
    String input = s.next(); Pattern p = Pattern.compile("\\\\");
    Matcher m = p.matcher(input);
    String r = m.replaceAll("_");
    System.out.println(r); Pattern p2 = Pattern.compile("\\", Pattern.LITERAL);
    Matcher m2 = p2.matcher(input);
    String r2 = m2.replaceAll("_");
    System.out.println(r2);
    }我把上面的例子修改了一个。
    楼主这个时候可以通过控制台输入:3g.qq.com:80\forward.jsp。试一下,可以达到同样的效果。
    这是因为当输入进去的时候是一个带有转义字符的字符串时,JDK内置会做转换工作,所以楼主在测试的时候就有误区。
      

  21.   


    你测试的时刻能不能写为String input = "3g.qq.com:80\forward.jsp",因为我实际的就是3g.qq.com:80\forward.jsp,还是说我哪里还有问题,帮忙指点指点
      

  22.   

    实际作用是这样的,数据库读取出来并传给我的是3g.qq.com:80\forward.jsp,我并不需要打印,打印只是测试,我需要的是把\转为_
      

  23.   


    - -1,我不跟楼主争了,楼主还是自己去实验一下吧。
    3g.qq.com:80\forward.jsp,假设你现在一个字符串,那么你打印出来如果是前面这个值的话,那你在测试的时候就写3g.qq.com:80\\forward.jsp,这没有问题,没有疑问。如果你的字符串就是3g.qq.com:80\forward.jsp,那么你在Java中打印的时候绝对不可能打印出“3g.qq.com:80\forward.jsp”这个效果,因为\f会被转义,所以你还是自己测试一下吧。无意义的争论还不如多测试一下。其实就是做一个简单的打印就完整了。
      

  24.   

    可以写个触发器嘛 每次插入值的时候就replaceAll("\","_")或者replaceAll("\","\\")一下。
      

  25.   

     LZ 我这样 写你明白了吧 select   translate( 'ABC5\fD6D ', '\', '_')   x   from   dual; 结贴吧...
    比刚才我说的数据字典 简单多了
      

  26.   


    不能在数据库插入时替换,因为别的地方也有用到这个数据,那些页面查出来的必须的url是真实的,也就是3g.qq.com:80\forward.jsp,而不是3g.qq.com:80\forward.jsp
      

  27.   

    我不能这么做,整个过程是这样的,一个页面查出url并显示,然后用户点击url旁边的一个链接,会把这个url传到后台来处理,而处理过程中就需要这样转换\
      

  28.   

    你测试的时刻能不能写为String input = "3g.qq.com:80\forward.jsp"-----
    不能,完毕。你写一个String input = "\f"  它打印出来不是\f,
    但是如果你在数据库里 有一个\f ,它打印之后就是\f,
    以上的话你能看明白不?所以,如果现在给你显示正确的值,这里的人能办到,但是你拿这段代码去套数据库出来的数据,它是错的,明白不?
      

  29.   

    select translate( 'ABC5\fD6D ', '\', '\\') x from dual;
      

  30.   


    select translate( 'ABC5\fD6D ', '\', '\\') x from dual;