天天看點

按照檔案名中包含的版本号資訊對檔案名清單進行排序

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()排出來的結果也是不正确的,必須要自己實作比較和排序方法)。

<code>copy </code><code>/A</code> <code>file1+file2+...+fileN ALLin1.sql</code>

3. 剪貼闆儲存拼接好的指令行

将拼接好的指令放入剪貼闆,這樣我就可以直接将拼好的指令粘貼到cmd終端并執行。(當然有朋友肯定要說Java也能直接調Shell。是的,為了懶省事,我沒有通過java來執行cmd指令。)

方案:

利用Netbeans寫出程式讀取檔案名,并對其進行排序。然後拼接成指令行,在cmd終端中執行。

關鍵點:

1. file1+file2+...+fileN的copy指令參數需要準備。但由于需要拼接的檔案太多(100多個檔案)手工準備這些參數不可行。

代碼:

<code>public</code> <code>class</code> <code>NewEmptyJUnitTest1 </code><code>implements</code> <code>ClipboardOwner {</code>

<code>    </code><code>public</code> <code>NewEmptyJUnitTest1() {</code>

<code>    </code><code>}</code>

<code>    </code><code>@BeforeClass</code>

<code>    </code><code>public</code> <code>static</code> <code>void</code> <code>setUpClass() {</code>

<code>    </code><code>@AfterClass</code>

<code>    </code><code>public</code> <code>static</code> <code>void</code> <code>tearDownClass() {</code>

<code>    </code><code>@Before</code>

<code>    </code><code>public</code> <code>void</code> <code>setUp() {</code>

<code>    </code><code>@After</code>

<code>    </code><code>public</code> <code>void</code> <code>tearDown() {</code>

<code>    </code><code>@Test</code>

<code>    </code><code>public</code> <code>void</code> <code>concatenateFileNamesInNameOrder() {</code>

<code>        </code><code>StringBuilder sb = </code><code>new</code> <code>StringBuilder(</code><code>"copy /A /Y "</code><code>);</code>

<code>        </code><code>List&lt;String&gt; fileNames = </code><code>new</code> <code>ArrayList&lt;&gt;();</code>

<code>        </code><code>File[] files;</code>

<code>        </code><code>File dir = </code><code>new</code> <code>File(</code><code>"C:\\Workspace\\Projects\\DB\\sql\\allinone"</code><code>);</code>

<code>        </code><code>files = dir.listFiles();</code>

<code>        </code><code>for</code> <code>(File file : files) {</code>

<code>            </code><code>fileNames.add(file.getName());</code>

<code>        </code><code>}</code>

<code>        </code><code>Collections.sort(fileNames, </code><code>new</code> <code>FileNameComparator());</code>

<code>        </code><code>int</code> <code>count = </code><code>0</code><code>;</code>

<code>        </code><code>for</code> <code>(String filename : fileNames) {</code>

<code>            </code><code>sb.append(filename).append(</code><code>"+"</code><code>);</code>

<code>            </code><code>count++;</code>

<code>        </code><code>sb.deleteCharAt(sb.lastIndexOf(</code><code>"+"</code><code>));</code>

<code>        </code><code>sb.append(</code><code>" ALLin1.sql"</code><code>);</code>

<code>          </code> 

<code>        </code><code>Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();</code>

<code>        </code><code>StringSelection ss = </code><code>new</code> <code>StringSelection(sb.toString());</code>

<code>        </code><code>clipboard.setContents(ss, NewEmptyJUnitTest1.</code><code>this</code><code>);</code>

<code>        </code><code>System.out.println(</code><code>"Total files: "</code> <code>+ count);</code>

<code>        </code><code>System.out.println(sb.toString());</code>

<code>    </code><code>@Override</code>

<code>    </code><code>public</code> <code>void</code> <code>lostOwnership(Clipboard clipboard, Transferable contents) {</code>

<code>        </code><code>throw</code> <code>new</code> <code>UnsupportedOperationException(</code><code>"Not supported yet."</code><code>); </code><code>//To change body of generated methods, choose Tools | Templates.</code>

<code>      </code> 

<code>    </code><code>private</code> <code>class</code> <code>FileNameComparator </code><code>implements</code> <code>Comparator&lt;String&gt; {</code>

<code>        </code><code>@Override</code>

<code>        </code><code>public</code> <code>int</code> <code>compare(String o1, String o2) {</code>

<code>            </code><code>int</code> <code>result = </code><code>0</code><code>;</code>

<code>            </code><code>int</code><code>[] ver1 = getVersionFields(o1);</code>

<code>            </code><code>int</code><code>[] ver2 = getVersionFields(o2);</code>

<code>            </code><code>for</code> <code>(</code><code>int</code> <code>i = </code><code>0</code><code>; i &lt; </code><code>4</code><code>; i++) {</code>

<code>                </code><code>result = ver1[i] - ver2[i];</code>

<code>                </code><code>if</code> <code>(result == </code><code>0</code><code>) {</code>

<code>                    </code><code>continue</code><code>;</code>

<code>                </code><code>} </code><code>else</code> <code>{</code>

<code>                    </code><code>return</code> <code>result;</code>

<code>                </code><code>}</code>

<code>            </code><code>}</code>

<code>            </code><code>return</code> <code>0</code><code>;</code>

<code>        </code><code>private</code> <code>int</code><code>[] getVersionFields(String str) {</code>

<code>            </code><code>String pattern = </code><code>"\\D*(\\d+\\.\\d+\\.\\d+\\.\\d+)\\D*"</code><code>;  </code><code>//0.0.0.0</code>

<code>            </code><code>String versionStr = str.replaceAll(pattern, </code><code>"$1"</code><code>);</code>

<code>            </code><code>String[] verFields = versionStr.split(</code><code>"\\."</code><code>);</code>

<code>              </code> 

<code>            </code><code>int</code><code>[] versionFields = </code><code>new</code> <code>int</code><code>[</code><code>4</code><code>];</code>

<code>            </code><code>Arrays.fill(versionFields, </code><code>0</code><code>, </code><code>3</code><code>, </code><code>0</code><code>);</code>

<code>            </code><code>int</code> <code>count = </code><code>0</code><code>;</code>

<code>            </code><code>for</code> <code>(String numStr : verFields) {</code>

<code>                </code><code>versionFields[count] = Integer.parseInt(numStr);</code>

<code>                </code><code>count++;</code>

<code>            </code><code>return</code> <code>versionFields;</code>

<code>}</code>

本文轉自 rickqin 51CTO部落格,原文連結:http://blog.51cto.com/rickqin/1358610