问题描述
我正在使用此功能来压缩一堆文件,但问题是如果有两个文件名内容不同但原始名称相同,那么只有一个文件被压缩,我如何通过添加来防止这种情况扩展名前的文件名编号,例如file1.txt
重复名称的号码扩展?
ZipOutputStream zipOut = new ZipOutputStream(response.getoutputStream())
files.forEach(file -> {
final ZipEntry zipEntry = new ZipEntry(Objects.requireNonNull(file.getoriginalName()));
zipOut.putNextEntry(zipEntry);
IoUtils.copy(file.getInputStream(),zipOut);
file.getInputStream().close();
zipOut.closeEntry();
}
用于复制
例如
files.add("hello");
files.add("hello");
files.add("hello");
files.add("name");
files.add("name");
files.add("name");
files.add("hello22");
files.add("name");
那么结果应该是
"hello","hello1","hello2","name","name1","name2","name3"
解决方法
假设您正在创建一个新的 zip 文件而不是编辑现有的 zip 存档,那么您可以遍历您的 files
列表,如果发现任何重复项,您可以在 HashMap 或类似的类似内容中记下新名称duplicateNameMap.put(oldNameString,newNameString);
,然后在您的 zip 方法中,您可以简单地检查 HashMap 并使用更新后的名称:
//Hashmap to store updated names
HashMap<String,String> duplicateNameMap = new HashMap<>();
//compare files to each other file to find duplicate names:
for (int i = 0; i < files.size(); i++) {
for (int j = i+1; j < files.size(); j++) {
//If duplicate exists then save the new name to the HashMap:
if(files.get(i).getOriginalName().equals(files.get(j).getOriginalName())) {
//Use substring to get the file name and extension
String name = files.get(i).getOriginalName().substring(0,files.get(i).getOriginalName().lastIndexOf("."));
//If the files have no extension ".doc" etc,then you can remove the next line
String extension = files.get(i).getOriginalName().substring(files.get(i).getOriginalName().lastIndexOf(".")+1);
//Use a method to count the number of previous files with the same name and set the correct duplicate number
String duplicateNumber = fixDuplicateName(files.get(i).getOriginalName());
//Store the new name in a hashmap using the old name as a key
duplicateNameMap.put(files.get(i).getOriginalName(),name + duplicateNumber + extension));
}
}
}
ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream());
//Then when saving files we can check the hashmap and update the files accordingly
files.forEach(file -> {
String name = file.getOriginalName();
//Check the HashMap to see if there is a duplicate then get the correct name from the hashmap:
if (duplicateNameMap.containsKey(file)) {
//Grab the new name from the hashmap
String newName = duplicateNameMap.get(name);
//Remove that entry from the hashmap so that it is not used again
duplicateNameMap.remove(name,newName);
//Assign the new name to be used
name = newName;
}
final ZipEntry zipEntry = new ZipEntry(name);
zipOut.putNextEntry(zipEntry);
IOUtils.copy(file.getInputStream(),zipOut);
file.getInputStream().close();
zipOut.closeEntry();
}
Here is the method used to count the number of duplicates and return the correct duplicate number:
public static String fixDuplicateName(HashMap<String,String> duplicateNameMap,String name) {
//Start the count at 1 (The first duplicate should always be 1)
int count = 1;
//Find out if there is more than 1 duplicate in the hashmap and increase the count if needed
for (String key: duplicateNameMap.keySet()) {
if (key.equals(name)) {
count++;
}
}
return count+"";
}
注意这样做的一个小副作用是第一个文件将添加“1”,第二个将添加“2”等,最后一个将是原始名称,但这几乎不是问题。如果 files
列表中的文件顺序很重要,那么您可以通过将每个名称添加到哈希映射中轻松修复它,即使它不是重复的,然后在 fixDuplicateName
方法中更改 { {1}} 到 int count = 1;
以便正确标记非重复项。然后在编写 zip 时只需从 hashmap 中获取每个文件名。