In Java, esiste un metodo per leggere una particolare riga da un file? Ad esempio, leggi la riga 32 o qualsiasi altro numero di riga.
In Java, esiste un metodo per leggere una particolare riga da un file? Ad esempio, leggi la riga 32 o qualsiasi altro numero di riga.
Risposte:
A meno che tu non abbia una conoscenza precedente delle righe nel file, non c'è modo di accedere direttamente alla 32a riga senza leggere le 31 righe precedenti.
Questo vale per tutte le lingue e tutti i file system moderni.
Quindi in modo efficace leggerai semplicemente le righe finché non avrai trovato la 32a.
Per file piccoli:
String line32 = Files.readAllLines(Paths.get("file.txt")).get(32)
Per file di grandi dimensioni:
try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
line32 = lines.skip(31).findFirst().get();
}
Non che io sappia, ma quello che potresti fare è scorrere le prime 31 righe senza fare nulla usando la funzione readline () di BufferedReader
FileInputStream fs= new FileInputStream("someFile.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
for(int i = 0; i < 31; ++i)
br.readLine();
String lineIWant = br.readLine();
Joachim ha ragione, ovviamente, e un'implementazione alternativa a quella di Chris (solo per file piccoli perché carica l'intero file) potrebbe essere quella di usare commons-io da Apache (anche se probabilmente potresti non voler introdurre una nuova dipendenza solo per questo, se lo trovi utile anche per altre cose, potrebbe avere senso).
Per esempio:
String line32 = (String) FileUtils.readLines(file).get(31);
http://commons.apache.org/io/api-release/org/apache/commons/io/FileUtils.html#readLines(java.io.File , java.lang.String)
Puoi provare il lettore di file indicizzati (licenza Apache 2.0). La classe IndexedFileReader ha un metodo chiamato readLines (int from, int to) che restituisce un SortedMap la cui chiave è il numero di riga e il valore è la riga che è stata letta.
Esempio:
File file = new File("src/test/resources/file.txt");
reader = new IndexedFileReader(file);
lines = reader.readLines(6, 10);
assertNotNull("Null result.", lines);
assertEquals("Incorrect length.", 5, lines.size());
assertTrue("Incorrect value.", lines.get(6).startsWith("[6]"));
assertTrue("Incorrect value.", lines.get(7).startsWith("[7]"));
assertTrue("Incorrect value.", lines.get(8).startsWith("[8]"));
assertTrue("Incorrect value.", lines.get(9).startsWith("[9]"));
assertTrue("Incorrect value.", lines.get(10).startsWith("[10]"));
L'esempio precedente legge un file di testo composto da 50 righe nel seguente formato:
[1] The quick brown fox jumped over the lazy dog ODD
[2] The quick brown fox jumped over the lazy dog EVEN
Disclamer: ho scritto questa libreria
Sebbene come detto in altre risposte, non sia possibile arrivare alla linea esatta senza conoscere prima l'offset (puntatore). Quindi, ho ottenuto questo risultato creando un file di indice temporaneo che memorizzerebbe i valori di offset di ogni riga. Se il file è abbastanza piccolo, puoi semplicemente memorizzare gli indici (offset) in memoria senza bisogno di un file separato per esso.
The offsets can be calculated by using the RandomAccessFile
RandomAccessFile raf = new RandomAccessFile("myFile.txt","r");
//above 'r' means open in read only mode
ArrayList<Integer> arrayList = new ArrayList<Integer>();
String cur_line = "";
while((cur_line=raf.readLine())!=null)
{
arrayList.add(raf.getFilePointer());
}
//Print the 32 line
//Seeks the file to the particular location from where our '32' line starts
raf.seek(raf.seek(arrayList.get(31));
System.out.println(raf.readLine());
raf.close();
Visita anche i documenti java per ulteriori informazioni: https://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html#mode
Complessità : è O (n) poiché legge l'intero file una volta. Si prega di essere consapevoli dei requisiti di memoria. Se è troppo grande per essere in memoria, crea un file temporaneo che memorizzi gli offset invece di ArrayList come mostrato sopra.
Nota : se tutto quello che vuoi nella riga "32", devi solo chiamare readLine () disponibile anche attraverso le altre classi "32" volte. L'approccio precedente è utile se si desidera ottenere più volte una riga specifica (basata sul numero di riga, ovviamente).
Grazie !
Un altro modo.
try (BufferedReader reader = Files.newBufferedReader(
Paths.get("file.txt"), StandardCharsets.UTF_8)) {
List<String> line = reader.lines()
.skip(31)
.limit(1)
.collect(Collectors.toList());
line.stream().forEach(System.out::println);
}
Se stai parlando di un file di testo, non c'è davvero modo di farlo senza leggere tutte le righe che lo precedono - Dopo tutto, le righe sono determinate dalla presenza di una nuova riga, quindi deve essere letta.
Usa un flusso che supporti readline, leggi le prime righe X-1 e scarica i risultati, quindi elabora quello successivo.
In Java 8,
Per file piccoli:
String line = Files.readAllLines(Paths.get("file.txt")).get(n);
Per file di grandi dimensioni:
String line;
try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
line = lines.skip(n).findFirst().get();
}
In Java 7
String line;
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
for (int i = 0; i < n; i++)
br.readLine();
line = br.readLine();
}
public String readLine(int line){
FileReader tempFileReader = null;
BufferedReader tempBufferedReader = null;
try { tempFileReader = new FileReader(textFile);
tempBufferedReader = new BufferedReader(tempFileReader);
} catch (Exception e) { }
String returnStr = "ERROR";
for(int i = 0; i < line - 1; i++){
try { tempBufferedReader.readLine(); } catch (Exception e) { }
}
try { returnStr = tempBufferedReader.readLine(); } catch (Exception e) { }
return returnStr;
}
Per me funziona: ho combinato la risposta di Leggere un semplice file di testo
Ma invece di restituire una stringa restituisco una LinkedList of Strings. Quindi posso selezionare la riga che desidero.
public static LinkedList<String> readFromAssets(Context context, String filename) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(context.getAssets().open(filename)));
LinkedList<String>linkedList = new LinkedList<>();
// do reading, usually loop until end of file reading
StringBuilder sb = new StringBuilder();
String mLine = reader.readLine();
while (mLine != null) {
linkedList.add(mLine);
sb.append(mLine); // process line
mLine = reader.readLine();
}
reader.close();
return linkedList;
}
Usa questo codice:
import java.nio.file.Files;
import java.nio.file.Paths;
public class FileWork
{
public static void main(String[] args) throws IOException {
String line = Files.readAllLines(Paths.get("D:/abc.txt")).get(1);
System.out.println(line);
}
}
Puoi usare LineNumberReader invece di BufferedReader. Passa attraverso l'API. Puoi trovare i metodi setLineNumber e getLineNumber.
Puoi anche dare un'occhiata a LineNumberReader, sottoclasse di BufferedReader. Insieme al metodo readline, ha anche metodi setter / getter per accedere al numero di riga. Molto utile per tenere traccia del numero di righe lette, durante la lettura dei dati dal file.
puoi usare la funzione skip () per saltare le righe dall'inizio.
public static void readFile(String filePath, long lineNum) {
List<String> list = new ArrayList<>();
long totalLines, startLine = 0;
try (Stream<String> lines = Files.lines(Paths.get(filePath))) {
totalLines = Files.lines(Paths.get(filePath)).count();
startLine = totalLines - lineNum;
// Stream<String> line32 = lines.skip(((startLine)+1));
list = lines.skip(startLine).collect(Collectors.toList());
// lines.forEach(list::add);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
list.forEach(System.out::println);
}
Sono tutti sbagliati, l'ho scritto in circa 10 secondi. Con questo sono riuscito a chiamare semplicemente object.getQuestion ("linoumber") nel metodo principale per restituire qualsiasi riga voglio.
public class Questions {
File file = new File("Question2Files/triviagame1.txt");
public Questions() {
}
public String getQuestion(int numLine) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(file));
String line = "";
for(int i = 0; i < numLine; i++) {
line = br.readLine();
}
return line; }}