2015-08-06 8 views
3

Мне нужно получить и удалить случайную строку из txt-файла (той же строки). До сих пор я придумал следующий код:Java: извлечение и удаление случайной строки из текстового файла

public String returnAndDeleteRandomLine(String dir) throws FileNotFoundException, IOException { 
    try (BufferedReader br = new BufferedReader(new FileReader(dir))) { 
     //StringBuilder sb = new StringBuilder(); 
     //System.out.println("Value of line before while() " + line); 

     ArrayList fileContents = new ArrayList(); 
     int maxLines = 0; 


     String line = br.readLine(); 
     //System.out.println("Value of line before while() " + line); 

     while (line != null) { 
      fileContents.add(line.toString()); 
      line = br.readLine(); 
      //System.out.println("Value of line is: " + line); 
     } 

     System.out.println("Value of maxLines() " + maxLines); 

     Random rand = new Random(); 
     int randomNumber = rand.nextInt(maxLines - 1) + 1; 
     System.out.println("Value of randomNumber: " + randomNumber); 
     int lineNumber = randomNumber; 

     if (fileContents.isEmpty()) { 
      return null; 
     } else System.out.println("Value of random line: " + fileContents.get(randomNumber).toString()); 
     return fileContents.get(randomNumber).toString(); 
    } 


} 

Но у меня все по-разному возникают ошибки. Самая последняя ошибка:

Значение MaxLines() 0 Исключение в потоке "основного" java.lang.IllegalArgumentException: оценка должна быть положительной при java.util.Random.nextInt (Unknown Source) в TransmitToFile.returnAndDeleteRandomLine (TransmitToFile.java:247) в Main.main (Main.java:98)

Я не мог работать даже на удалении линии, потому что я до сих пор не удалось получить линию.

ответ

0

Проблема заключается линия

int randomNumber = rand.nextInt(maxLines - 1) + 1; 

В случае, когда maxLines является 0, то вы звоните rand.nextInt(-1). Отсюда следует, что этот параметр должен быть положительным.

1

Вы забыли, так что задайте значение переменной maxLines для нумера строк в файле, а с момента его получения вы получите исключение.

Вы можете добавить новый метод, чтобы получить номера строк, как это (как показано в этом ответе: number-of-lines-in-a-file-in-java):

public int countLines(String filename) throws IOException { 
     LineNumberReader reader = new LineNumberReader(new FileReader(filename)); 
     int cnt = 0; 
     String lineRead = ""; 
     while ((lineRead = reader.readLine()) != null) { 
     } 

     cnt = reader.getLineNumber(); 
     reader.close(); 
     return cnt; 
    } 

И изменить код с:

int maxLines = 0; 

к:

int maxLines = countLines(dir); 

Так что переменная maxLines будет равна числу строк в вашем файле.

+0

Если файл пуст (MAXLINES = 0), это решение все равно не получится, так что вы также должны сделать чек, если (MaxLines = 0) возвращение; или что-то. Наверное, не большая проблема в реальной жизни, но стоит отметить. – Astrogat

0

Ошибка в этой строке:

int randomNumber = rand.nextInt(maxLines - 1) + 1; 

Вы должны добавить проверку, чтобы проверить размер первого:

int totalLines = maxLines - 1; 
if(totalLines > 0) { 
    Random rand = new Random(); 
    int randomNumber = rand.nextInt (totalLines) + 1; 
    System.out.println("Value of randomNumber: " + randomNumber); 
    } else { 
     return null; 
    } 
1

Random.nextInt(N) поставляет 0 .. N-1. Поскольку все индексы подсчитываются от 0, но люди считаются с 1, произошел переполох.

Общий код можно сделать проще:

public static String returnAndDeleteRandomLine(String dir) throws IOException { 
    Path path = Paths.get(dir); 
    List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8); 
    if (lines.isEmpty()) { 
     throw new IOException("Empty file: " + dir); 
    } 
    Random rand = new Random(); 
    int lineIndex = rand.nextInt(lines.size()); // 0 .. lines.size() - 1 
    String line = lines.get(lineIndex); 

    System.out.printf("Line %d: %s%n", (lineIndex + 1), line); 

    lines.remove(lineIndex); 
    Files.write(path, lines, StandardCharsets.UTF_8, 
      StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING); 
    return line; 
}