2015-04-05 2 views
1

Недавно одна из моих серверов данных снизилась и повреждено большое количество видеофайлов (более 15 000 файлов или более 60 ТБ). Я написал сценарий, чтобы проверить все файлы и поместить результаты в очень большой файл log.txt (почти 8 ГБ).Поиск ближайшего номера от двух арраистов

Я написал код, чтобы найти все строки, начинающиеся с "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

Пример вы предоставляете не то, что вы описали: "если list1 содержит числа {1, 5, 45, 55, 100, 2000 ... и т. д.}, а list2 содержит числа {50, 51, 53, 2010 ... и т. д.}, результат должен быть {45, 2000 ... и т.д.} Зачем? Пожалуйста, объясните, как эти списки имеют этот результат. –

+0

У вас есть определенный диапазон? Например, если цифры имеют разницу менее 50, она должна выводиться? – russellsayshi

+0

Какой следующий номер после 1796 года? – CMPS

ответ

0

вы определили два сканера (кажется ненужным), но вы только с помощью одного из них и вызывая nextline() дважды по нему. Похоже, что это не предназначено, и, как следствие, результаты, которые вы получаете, ошибочны. Было бы очень полезно, если бы вы могли опубликовать образец выдержки из вашего файла журнала (вы можете фильтровать конфиденциальные данные), чтобы мы могли определить, какой лучший подход для этого.

Я думаю, вы должны отказаться от своего нынешнего подхода, потому что это не похоже на эффективный способ решить вашу проблему необходимости поиска файлов с поврежденными файлами.

В зависимости от того, как выглядят ваши данные, вы можете использовать регулярные выражения и, возможно, даже извлекать имена файлов непосредственно в Set.

Редактировать: Добавлен код, который должен выполнить эту работу для вас, если вы действительно правы, что каждый файл начинается с «Input # 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': 
+0

Я отредактировал мой вопрос и добавил два частичных журнала. – DroidX

+0

Спасибо, спасибо, спасибо. Работает как шарм, и это невероятно быстро. Один из моих коллег попробовал что-то подобное в C#, и для получения результата из образца журнала 200Mb потребовалось почти 2 часа, этот код завершился за 8 секунд. Спасибо, мой друг за вашу большую помощь. – DroidX

+0

Рад помочь. Еще одна вещь. Вы можете рассмотреть возможность использования HashSet вместо LinkedHashSet, если вы не занимаетесь упорядочением имен файлов, которые вы извлекаете. HashSet немного эффективнее, и я считаю, что с файлом журнала 8gb вам нужна вся производительность, которую вы можете получить. –

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] 
+0

Я попытаюсь реализовать свой код и дождаться результата. – DroidX

+0

@DroidX это сработало? – CMPS

+0

Код работает хорошо для первых 2.800.000 строк, но затем останавливается и не будет продолжаться. Брайем решил с другим подходом. Спасибо за помощь, это было очень полезно. – DroidX

Смежные вопросы