Too主要是想实践一下Java的Comparator的用法。


我有一个文件夹,里面包含了100多个sql脚本文件,每个文件都是以update-x.x.x.x.sql的形式命名的,其中x.x.x.x为纯数字版本号。我想将这些SQL文件中的内容收尾相连复制到一个文件中(windows7下cmd终端上允许8k多字符的单行命令,嘘~幸亏没超过)。


分析:

1. 获取文件名

由于需要拼接的文件太多,决定写一段程序从指定文件夹中读出所有需要拼接在一起的文件的文件名并将获得的文件名用+号连接起来。

2. 文件名排序

虽然可以很容易获得一个文件夹下的所有文件的文件名,但困难的是如何对这些获取到的文件名进行排序。而且,排序的依据是每个文件名中包含的x.x.x.x版本信息。每个x为正整数集中的一个数字。问题又来了,在Java中,默认的字符串比较运算得出的结果是1.0.0.1, 1.0.0.10, 1.0.0.11, 1.0.0.2 ...看到问题了吧,这种排序方法显然不是数值自然排序法(即便使用Collections.sort()排出来的结果也是不正确的,必须要自己实现比较和排序方法)。

1
copy  /A  file1+file2+...+fileN ALLin1.sql

3. 剪贴板保存拼接好的命令行

将拼接好的命令放入剪贴板,这样我就可以直接将拼好的命令粘贴到cmd终端并执行。(当然有朋友肯定要说Java也能直接调Shell。是的,为了懒省事,我没有通过java来执行cmd命令。)


方案:

利用Netbeans写出程序读取文件名,并对其进行排序。然后拼接成命令行,在cmd终端中执行。


1
 

关键点:

1. file1+file2+...+fileN的copy命令参数需要准备。但由于需要拼接的文件太多(100多个文件)手工准备这些参数不可行。


代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
public  class  NewEmptyJUnitTest1  implements  ClipboardOwner {
     public  NewEmptyJUnitTest1() {
     }
     @BeforeClass
     public  static  void  setUpClass() {
     }
     @AfterClass
     public  static  void  tearDownClass() {
     }
     @Before
     public  void  setUp() {
     }
     @After
     public  void  tearDown() {
     }
     @Test
     public  void  concatenateFileNamesInNameOrder() {
         StringBuilder sb =  new  StringBuilder( "copy /A /Y " );
         List<String> fileNames =  new  ArrayList<>();
         File[] files;
         File dir =  new  File( "C:\\Workspace\\Projects\\DB\\sql\\allinone" );
         files = dir.listFiles();
         for  (File file : files) {
             fileNames.add(file.getName());
         }
         Collections.sort(fileNames,  new  FileNameComparator());
         int  count =  0 ;
         for  (String filename : fileNames) {
             sb.append(filename).append( "+" );
             count++;
         }
         sb.deleteCharAt(sb.lastIndexOf( "+" ));
         sb.append( " ALLin1.sql" );
           
         Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
         StringSelection ss =  new  StringSelection(sb.toString());
         clipboard.setContents(ss, NewEmptyJUnitTest1. this );
           
         System.out.println( "Total files: "  + count);
         System.out.println(sb.toString());
     }
     @Override
     public  void  lostOwnership(Clipboard clipboard, Transferable contents) {
         throw  new  UnsupportedOperationException( "Not supported yet." );  //To change body of generated methods, choose Tools | Templates.
     }
       
     private  class  FileNameComparator  implements  Comparator<String> {
         @Override
         public  int  compare(String o1, String o2) {
             int  result =  0 ;
             int [] ver1 = getVersionFields(o1);
             int [] ver2 = getVersionFields(o2);
             for  ( int  i =  0 ; i <  4 ; i++) {
                 result = ver1[i] - ver2[i];
                 if  (result ==  0 ) {
                     continue ;
                 else  {
                     return  result;
                 }
             }
             return  0 ;
         }
           
         private  int [] getVersionFields(String str) {
             String pattern =  "\\D*(\\d+\\.\\d+\\.\\d+\\.\\d+)\\D*" ;   //0.0.0.0
             String versionStr = str.replaceAll(pattern,  "$1" );
             String[] verFields = versionStr.split( "\\." );
               
             int [] versionFields =  new  int [ 4 ];
             Arrays.fill(versionFields,  0 3 0 );
             int  count =  0 ;
             for  (String numStr : verFields) {
                 versionFields[count] = Integer.parseInt(numStr);
                 count++;
             }
             return  versionFields;
         }
     }
}