最近我的一台数据服务器出现故障,大量视频文件损坏(超过15,000个文件,或超过60TB)。我写了一个脚本来检查所有文件并将结果放在一个非常大的log.txt文件中(差不多8GB)。
我编写代码来查找以"Input #0"
开头的所有行和包含"damaged"
的行,然后将其行号添加到ArrayList
。接下来,我需要比较这两个ArrayLists并找到list2
中与list1
中的数字最接近的行号,这样我就可以从日志文件中找回文件名。
例如:
如果list1
包含数字{1,5,45,55,100,2000 ......等}
list2
包含数字{50,51,53,2010 ...等},结果应为{45,2000 ......等}
这是我目前的代码:
import java.io.*;
import java.util.*;
public class Log {
public static void main(String [] args) throws IOException{
ArrayList<Integer> list1 = new ArrayList<Integer>();
ArrayList<Integer> list2 = new ArrayList<Integer>();
File file = new File("C:\\log.txt");
try {
Scanner scanner = new Scanner(file);
Scanner scanner2 = new Scanner(file);
int lineNum = 0;
int lineNum2 = 0;
while (scanner.hasNextLine()){
String line = scanner.nextLine();
String line2 = scanner.nextLine();
lineNum++;
lineNum2++;
if((line.startsWith("Input #0"))) {
list1.add(lineNum);
}
if((line2.contains("damaged"))) {
list2.add(lineNum2);
}
}
这是我从上面的代码中得到的:
list1 [5, 262, 304, 488, 523, 1189, 1796, 2503, 2722, 4052, 4201, 4230, 4298, 4312, 4559, 4887, 4903, 5067....]
list2 [1838, 1841, 1842, 1844, 1851, 1861, 1865, 1866, 1868, 1875, 1878, 1879, 1880, 1881, 1886, 1887, 1891....]
一些日志数据:
Input #0, mpegvideo, from '/cinegy/cinegy/VIDEO/BSF/BLOK 3 - 14. NOVHighb668ca7d201411141051110636.m2v':
.
.
.
.
.
.
有损坏的数据:
Input #0, mpegvideo, from '/cinegy/cinegy/VIDEO/BSF/BLOK 3 - 14. NOVHighb668ca7d201411141051110636.m2v':
.
.
.
.
.
[error 0x090010] file damaged at 16 09
[error 0x090010] file damaged at 19 15
每个文件的日志不包含任何模式,除了前5-6行左右。损坏和未损坏的文件都包含20到100多行的信息。
因此,从这些数字来看,第一个结果应该是1796号。
我几乎是Java的新手,我需要帮助。
答案 0 :(得分:1)
这是一个可以完成工作的小代码,但我不知道你是否想要在结果中使用冗余值,所以我将它们保存在列表和集合中,选择你喜欢的那个:
public static void main(String[] args) {
int[] list1 = {5, 262, 304, 488, 523, 1189, 1796, 2503, 2722, 4052, 4201, 4230, 4298, 4312, 4559};
int[] list2 = {1838, 1841, 1842, 1844, 1851, 1861, 1865, 1866, 1868, 1875, 1878, 1879, 1880, 1881};
ArrayList<Integer> resultList = new ArrayList<Integer>();
Set<Integer> resultSet = new HashSet<Integer>();
int j = 0;
for(int i = 0; i < list2.length; i++){
for(; j < list1.length; j++){
if(list1[j] > list2[i])
break;
}
resultList.add(list1[j-1]);
resultSet.add(list1[j-1]);
}
System.out.println(resultList);
System.out.println(resultSet);
}
输出:
[1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796]
[1796]
答案 1 :(得分:0)
您定义了两个扫描程序(似乎没有必要),但您只使用其中一个并在其上调用nextline()两次。看起来这不是故意的,因此你得到的结果是错误的。如果您可以从日志文件中发布样本摘录(您可以过滤敏感数据),这将非常有用,这样我们就可以确定最佳方法。
我认为您应该废弃当前的方法,因为它似乎不是解决您需要查找损坏文件的文件名的问题的有效方法。
根据数据的外观,您可以使用正则表达式,甚至可以直接将文件名提取到Set中。
编辑:如果确实每个文件都以“输入#0”开头,那么添加一些应该为您完成工作的粗略代码。只要每个文件的日志数据中都有一个模式,那么您应该始终能够直接提取所需的数据,而不是通过两个单独的arraylists中的匹配条目。
public static void main(String [] args) throws FileNotFoundException{
Set<String> damagedFiles = new LinkedHashSet<String>();
File file = new File("C:\\log.txt");
Scanner scanner = new Scanner(file);
String filename = null;
try {
int lineNum = 0;
while (scanner.hasNextLine()){
String line = scanner.nextLine();
if(line.startsWith("Input #0")){
/*if desired, can use a regex lookahead to get only the path and filename
instead of the entire Input #0 line */
filename = line;
}
if(line.contains("damaged")){
if (filename != null){
damagedFiles.add(filename);
}
}
}
} finally {
scanner.close();
for (String s : damagedFiles){
System.out.println(s);
}
}
}
这是我在示例日志文件上运行此代码时得到的结果,我在其中命名了损坏的文件dmg#.m2v
Input #0, mpegvideo, from '/cinegy/cinegy/VIDEO/BSF/BLOK 3 - 14. dmg1.m2v':
Input #0, mpegvideo, from '/cinegy/cinegy/VIDEO/BSF/BLOK 3 - 14. dmg2.m2v':
Input #0, mpegvideo, from '/cinegy/cinegy/VIDEO/BSF/BLOK 3 - 14. dmg3.m2v':
Input #0, mpegvideo, from '/cinegy/cinegy/VIDEO/BSF/BLOK 3 - 14. dmg4.m2v':