[英]Java - renaming output file if name already exists with an increment, taking into account existing increments
構建一個Android應用程序時,我遇到了進行一些文件復制的需求。 我想通過在文件名中添加“(increment)”字符串來獲取已使用文件名的新文件名的方法。 例如
text.txt ---> text(1).txt
算法應說明以下問題
1)如果text.txt
存在,則新文件名NEVER
應該是text.txt(1)
2)如果text(1).txt
存在,則新文件名應為text(2).txt
而不是text(1)(1).txt
3)如果text(1)foo.txt
存在,則新文件名應為text(1)foo(1).txt
我已經准備好了第一個,但是第二個卻遇到了困難。 正則表達式不是我的強項!(使用Regex不是強制性的。歡迎使用每種方法)有幫助嗎?
回答:
結合我的原始代碼和這里的答案之一,我最終得出了結論,無論文件是否具有擴展名,它在所有情況下都對我非常有效:
public static File getFinalNewDestinationFile(File destinationFolder, File fileToCopy){
String destFolderPath = destinationFolder.getAbsolutePath()+File.separator;
File newFile = new File(destFolderPath + fileToCopy.getName());
String filename=fileToCopy.getName();
String nameWithoutExtentionOrIncrement;
String extension = getFileExtension(filename);
if(extension!=null){
extension="."+extension;
int extInd = filename.lastIndexOf(extension);
nameWithoutExtentionOrIncrement = new StringBuilder(filename).replace(extInd, extInd+extension.length(),"").toString();
}
else{
extension="";
nameWithoutExtentionOrIncrement = filename;
}
int c=0;
int indexOfClose = nameWithoutExtentionOrIncrement.lastIndexOf(")");
int indexOfOpen = nameWithoutExtentionOrIncrement.lastIndexOf("(");
if(indexOfClose!=-1 && indexOfClose!=-1 && indexOfClose==nameWithoutExtentionOrIncrement.length()-1 && indexOfClose > indexOfOpen && indexOfOpen!=0){
String possibleNumber = nameWithoutExtentionOrIncrement.substring(indexOfOpen+1, indexOfClose);
try{
c = Integer.parseInt(possibleNumber);
nameWithoutExtentionOrIncrement=nameWithoutExtentionOrIncrement.substring(0, indexOfOpen);
}catch(Exception e){c=0;}
}
while(newFile.exists()){
c++;
String path = destFolderPath + nameWithoutExtentionOrIncrement +"(" + Integer.toString(c) + ")" + extension;
newFile = new File(path);
}
return newFile;
}
public static String getFileExtension(String filename) {
if (filename == null) { return null; }
int lastUnixPos = filename.lastIndexOf('/');
int lastWindowsPos = filename.lastIndexOf('\\');
int indexOfLastSeparator = Math.max(lastUnixPos, lastWindowsPos);
int extensionPos = filename.lastIndexOf('.');
int lastSeparator = indexOfLastSeparator;
int indexOfExtension = lastSeparator > extensionPos ? -1 : extensionPos;
int index = indexOfExtension;
if (index == -1) {
return null;
} else {
return filename.substring(index + 1).toLowerCase();
}
}
使用一種正則表達式模式:
final static Pattern PATTERN = Pattern.compile("(.*?)(?:\\((\\d+)\\))?(\\.[^.]*)?");
String getNewName(String filename) {
if (fileExists(filename)) {
Matcher m = PATTERN.matcher(filename);
if (m.matches()) {
String prefix = m.group(1);
String last = m.group(2);
String suffix = m.group(3);
if (suffix == null) suffix = "";
int count = last != null ? Integer.parseInt(last) : 0;
do {
count++;
filename = prefix + "(" + count + ")" + suffix;
} while (fileExists(filename));
}
}
return filename;
}
正則表達式模式說明:
(.*?)
非貪婪的“匹配所有內容” (?:\\\\((\\\\d+)\\\\))?
括號中的數字(可選)
(?:____________)
-是一個非捕獲組 ___\\\\(______\\\\)_
匹配(
和)
______(\\\\d+)____
匹配並捕獲一個或多個數字 (\\\\.[^.]+)?
點號后跟除點號之外的任何內容(可選) 這是一種實現方法:
String fileName;
File file = new File(fileName);
if(file.exists()) {
int dot = fileName.lastIndexOf('.'), open = fileName.lastIndexOf('('), incr;
boolean validNum = false;
if(fileName.charAt(dot-1) == ')' && open != -1){
String n = fileName.substring(open+1, dot-1);
try {
incr = Integer.parseInt(n);
validNum = true;
} catch(NumberFormatException e) {
validNum = false;
}
}
if(validNum) {
String pre = fileName.substring(0, open+1), post = fileName.substring(0, dot-1);
while(new File(pre + ++incr + post).exists());
fileName = pre + incr + post;
} else {
fileName = fileName.substring(0, dot) + "(1)" + fileName.substring(dot);
}
}
我假設幾件事:
1)可以使用一種名為fileExists(String fileName)的方法。 如果文件系統中已經存在具有指定名稱的文件,則返回true。
2)有一個名為FILE_NAME的常量,在您的示例中等於“ text”。
if (!fileExists(FILE_NAME)) {
//create file with FILE_NAME.txt as name
}
int availableIndex = 1;
while (true) {
if (!fileExists(currentName)) {
//create file with FILE_NAME(availableIndex).txt
break;
}
availableIndex++;
}
我對Android不太確定,但是由於它是Java程序,因此您可以在要編寫的目錄中創建File對象。 有了它后,您可以看到其中已經存在的文件名列表以及其他相關信息。 然后,您可以根據上述邏輯確定文件名。
File dir = new File("<dir-path>");
if(dir.isDirectory()){
String[] files = dir.list();
for(String fileName : files){
<logic for finding filename>
}
}
如果所有文件名都具有擴展名,則可以執行以下操作(僅作為示例,您必須對其進行更改以適合您的情況):
public static void main(String[] args)
{
String test = "test(1)foo.txt";
String test1 = "test(1)foo(1).txt";
Pattern pattern = Pattern.compile("((?<=\\()\\d+(?=\\)\\.))");
Matcher matcher = pattern.matcher(test);
String fileOutput = "";
String temp = null;
int newInt = -1;
while(matcher.find())
{
temp = matcher.group(0);
}
if(temp != null)
{
newInt = Integer.parseInt(temp);
newInt++;
fileOutput = test.replaceAll("\\(\\d+\\)(?=\\.(?!.*\\.))", "(" + newInt + ")");
}
else
{
fileOutput = test;
}
System.out.println(fileOutput);
matcher = pattern.matcher(test1);
fileOutput = "";
temp = null;
while(matcher.find())
{
temp = matcher.group(0);
}
if(temp != null)
{
newInt = Integer.parseInt(temp);
newInt++;
fileOutput = test1.replaceAll("\\(\\d+\\)(?=\\.(?!.*\\.))", "(" + newInt + ")");
}
else
{
fileOutput = test1;
}
System.out.println(fileOutput);
}
輸出:
測試(1)foo.txt
測試(1)富(2).txt
它使用正則表達式在last之前的()
查找數字.
。
更新資料
replaceAll()
更改為處理存在的情況.
在test(1).foo(1).txt
的第一個(1)
之后。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.