java中获取文件总行数_关于java:如何以有效的方式获取文件中的行数?
本問題已經有最佳答案,請猛點這里訪問。
我有一個大文件。 它包括大約3.000-20.000行。 如何使用Java獲取文件中的行總數?
從你的評論到答案來判斷,你要找的詞是"有效的",而不是"有效的"。
是的,你是對的
@Firstthumb:請不要在人們回復評論后刪除評論。 對于那些遲到演出的人來說,這讓線程變得混亂。
為什么? 20,000線并不大。 數百萬人很大。 為什么你認為你需要知道線的數量? 如果這樣做,您可以在處理它們時對它們進行計數。 您必須讀取整個文件才能計算行數。 你也可以同時做一些有用的事情。
BufferedReader reader = new BufferedReader(new FileReader("file.txt"));
int lines = 0;
while (reader.readLine() != null) lines++;
reader.close();
更新:為了回答這里提出的性能問題,我做了一個測量。第一件事:20.000行太少,以使程序運行一段時間。我創建了一個包含500萬行的文本文件。這個解決方案(從沒有像-server或-XX-options這樣的參數的java開始)在我的盒子上需要大約11秒。與wc -l(UNIX命令行工具計數行)相同,為11秒。讀取每個字符并尋找' n'的解決方案需要104秒,9-10倍。
你的意思是什么?性能?在這種情況下,你將沒有更好的方法,因為行可以有不同的長度,你必須讀取完整的文件,計算行數(wc也這樣做)。如果你談論編程效率,我肯定你可以把它放在一個實用程序方法(或者一些常見的庫已經完成它)。
@Firstthumb。可能效率不高,但誰在乎呢。他只計算20k線,非常小。這段代碼得到了我最簡單的投票。
LineNumberReader的效率如何,因為它擴展了BufferedReader?
沒有人說這比LineNumberReader好,至少我不這樣做。
下一個問題?你為什么不這樣做:D
我有點確定,BufferedReader的工作速度至少和FileReader一樣快,并檢查每一個字符。我通過測量時間證明了這一點(并且實際上表明檢查每個字符的速度要慢得多)。但我認為LineNumberReader解決方案的效果與BufferedReader的解決方案一樣好。這就是我贊成這個答案的原因。
檢查每個字節應該肯定更快(使用緩沖區時),因為FileReader必須將字節解碼為文本。
對于現代Java,Augustin的答案應該是可接受的答案。使用Files.lines。
Files.lines
使用Files.lines使用NIO時,Java 8+有一個非常好的簡短方法。
Path path = Paths.get("./big_file.txt");
long lineCount = Files.lines(path).count();
UTF-8中的默認字符編碼。您可以指定備用編碼以匹配您的特定數據文件。
床解決方案。我們可以遇到charset的問題
charset默認為UTF-8
@Mikhail將特定數據文件的字符編碼作為可選第二個參數中的Charset對象傳遞。見:Files.lines(Path path, Charset cs)。默認值為UTF-8;其他編碼通過Charset。
Files.lines(路徑).Count之間();不應該直接使用。相反,請嘗試使用資源。示例:: long lineCount; try(Stream linesStream = Files.lines(path)){lineCount = linesStream.count(); }
使用LineNumberReader
就像是
public static int countLines(File aFile) throws IOException {
LineNumberReader reader = null;
try {
reader = new LineNumberReader(new FileReader(aFile));
while ((reader.readLine()) != null);
return reader.getLineNumber();
} catch (Exception ex) {
return -1;
} finally {
if(reader != null)
reader.close();
}
}
您可能還需要關閉()讀者。
是的;謝謝:D
你可能要在finally塊中檢查讀者!= null
@dfa謝謝,修復
我找到了一些解決方案,它可能對你有用
下面是代碼片段,計算文件中的no.of行。
File file = new File("/mnt/sdcard/abc.txt");
LineNumberReader lineNumberReader = new LineNumberReader(new FileReader(file));
lineNumberReader.skip(Long.MAX_VALUE);
int lines = lineNumberReader.getLineNumber();
lineNumberReader.close();
結果是行count - 1
實際上結果是lines + 1
結果是getLineNumber()加1,因為行索引從0開始
它也適用于其他文件嗎?像.csv,.xls,.xlsx?
這大約和它可以獲得的效率一樣,緩沖二進制讀取,沒有字符串轉換,
FileInputStream stream = new FileInputStream("/tmp/test.txt");
byte[] buffer = new byte[8192];
int count = 0;
int n;
while ((n = stream.read(buffer)) > 0) {
for (int i = 0; i < n; i++) {
if (buffer[i] == '
') count++;
}
}
stream.close();
System.out.println("Number of lines:" + count);
讀取文件并計算換行符的數量。使用Java讀取文件的簡單方法是java.util.Scanner類,一次一行。
您需要精確的行數還是僅需要近似值?我碰巧并行處理大文件,通常我不需要知道確切的行數 - 然后我恢復采樣。將文件拆分為10個1MB塊并計算每個塊中的行數,然后將其乘以10,您將獲得非常好的行計數近似值。
在具有1380萬行的文件上測試時,此解決方案比最高評級答案快3.6倍。它只是將字節讀入緩沖區并計算字符。您可以使用緩沖區大小,但在我的機器上,任何超過8KB的內容都不會使代碼更快。
private int countLines(File file) throws IOException {
int lines = 0;
FileInputStream fis = new FileInputStream(file);
byte[] buffer = new byte[BUFFER_SIZE]; // BUFFER_SIZE = 8 * 1024
int read;
while ((read = fis.read(buffer)) != -1) {
for (int i = 0; i < read; i++) {
if (buffer[i] == '
') lines++;
}
}
fis.close();
return lines;
}
我想知道使用預編譯的RegEx模式是否會使其更快或更慢。我相信它能做的就是與所有線路結束一起工作。并且,我認為它也可能使它更快。
如果好處有幫助,上述一些解決方案也可以利用緩沖。例如,"new LineNumberReader(new FileReader(theFilePathStr),8096)"等等。
小心字符編碼......
快速而骯臟,但它完成了工作:
import java.io.*;
public class Counter {
public final static void main(String[] args) throws IOException {
if (args.length > 0) {
File file = new File(args[0]);
System.out.println(countLines(file));
}
}
public final static int countLines(File file) throws IOException {
ProcessBuilder builder = new ProcessBuilder("wc","-l", file.getAbsolutePath());
Process process = builder.start();
InputStream in = process.getInputStream();
LineNumberReader reader = new LineNumberReader(new InputStreamReader(in));
String line = reader.readLine();
if (line != null) {
return Integer.parseInt(line.trim().split("")[0]);
} else {
return -1;
}
}
}
一方面效果,這個解決方案不是跨平臺的。
之前的所有答案都建議讀取整個文件并計算您在執行此操作時找到的換行數量。你評價一些"無效",但這是你能做到的唯一方法。"行"不是文件中的簡單字符。要計算該字符,您必須查看文件中的每個字符。
對不起,你別無選擇。 :-)
如果已經發布的答案不夠快,您可能需要尋找特定于您的特定問題的解決方案。
例如,如果這些文本文件是僅附加到的日志,并且您經常需要知道其中的行數,則可以創建索引。此索引將包含文件中的行數,上次修改文件的時間以及文件的大小。這將允許您通過跳過已經看過的所有行并只讀取新行來重新計算文件中的行數。
+1這可能是一個合適的在線算法。
嘗試使用unix"wc"命令。我不是故意使用它,我的意思是下載源代碼并看看它們是如何做到的。它可能在c中,但您可以輕松地將行為移植到java。制作自己的問題是考慮結束cr / lf問題。
舊帖子,但我有一個可以為下一個人提供幫助的解決方案。
為什么不直接使用文件長度來了解進展情況?當然,行必須幾乎相同的大小,但它適用于大文件:
public static void main(String[] args) throws IOException {
File file = new File("yourfilehere");
double fileSize = file.length();
System.out.println("=======> File size =" + fileSize);
InputStream inputStream = new FileInputStream(file);
InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"iso-8859-1");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
int totalRead = 0;
try {
while (bufferedReader.ready()) {
String line = bufferedReader.readLine();
// LINE PROCESSING HERE
totalRead += line.length() + 1; // we add +1 byte for the newline char.
System.out.println("Progress ===>" + ((totalRead / fileSize) * 100) +" %");
}
} finally {
bufferedReader.close();
}
}
它允許在不對文件進行任何完整讀取的情況下查看進度。我知道這取決于很多元素,但我希望它會有用:)。
[版]
這是一個估計時間的版本。我把一些SYSO用于顯示進度和估算。我看到你處理足夠的線后你有一個很好的時間估計誤差(我嘗試使用10M線,并且在1%的治療后,時間估計精確到95%)。
我知道,有些值必須在變量中設置。這段代碼寫得很快,但對我來說很有用。希望它也適合你:)。
long startProcessLine = System.currentTimeMillis();
int totalRead = 0;
long progressTime = 0;
double percent = 0;
int i = 0;
int j = 0;
int fullEstimation = 0;
try {
while (bufferedReader.ready()) {
String line = bufferedReader.readLine();
totalRead += line.length() + 1;
progressTime = System.currentTimeMillis() - startProcessLine;
percent = (double) totalRead / fileSize * 100;
if ((percent > 1) && i % 10000 == 0) {
int estimation = (int) ((progressTime / percent) * (100 - percent));
fullEstimation += progressTime + estimation;
j++;
System.out.print("Progress ===>" + percent +" %");
System.out.print(" - current progress :" + (progressTime) +" milliseconds");
System.out.print(" - Will be finished in ===>" + estimation +" milliseconds");
System.out.println(" - estimated full time =>" + (progressTime + estimation));
}
i++;
}
} finally {
bufferedReader.close();
}
System.out.println("Ended in" + (progressTime) +" seconds");
System.out.println("Estimative average ===>" + (fullEstimation / j));
System.out.println("Difference:" + ((((double) 100 / (double) progressTime)) * (progressTime - (fullEstimation / j))) +"%");
如果您認為這是一個很好的解決方案,請隨意改進此代碼。
逐行讀取文件并為每行增加一個計數器,直到您讀完整個文件。
在我的測試中,其他答案在118.5k行文件上需要~150-300ms。
以下需要1ms,但只是近似值(報告117k行),并且取決于每條線具有相似的大小。
private static void countSize(File file) {
long fileLength = file.length();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
//Skip header as it is of different size
reader.readLine();
String text = reader.readLine();
int lineLength = text.length();
long lines = fileLength / lineLength;
System.out.println(lines);
} catch(IOException e) {
e.printStackTrace();
} finally {
if(reader != null) {
try {
reader.close();
} catch(IOException e) {
//no-op
}
}
}
}
純Java中最快的解決方案可能是使用NIO Channel將文件作為字節讀入大型ByteBuffer。然后根據相關的行分隔符約定,使用您對文件編碼方案的了解,對編碼的CR和/或NL字節進行計數。
最大化吞吐量的關鍵是:
確保以大塊讀取文件,
避免將字節從一個緩沖區復制到另一個緩沖區
避免將字節復制/轉換為字符,以及
避免分配對象來表示文件行。
實際的代碼太復雜了,我無法動態編寫。此外,OP并不是要求最快的解決方案。
緩沖的閱讀器過度 strike>
Reader r = new FileReader("f.txt");
int count = 0;
int nextchar = 0;
while (nextchar != -1){
nextchar = r.read();
if (nextchar == Character.getNumericValue('
') ){
count++;
}
}
我對一個簡單例子的搜索創建了一個實際上很差的例子。對單個字符重復調用read()不是最佳的。請參閱此處的示例和測量。
BufferedReader可以很好地處理不同的行尾。您的解決方案忽略了Mac-line-endings(' r')。那可能沒問題。無論如何,您的解決方案暫時無法從文件中實際讀取。我想你忘了一條線。
什么會改變nextchar在這里?如果你要在每次迭代時調用read(),我強烈懷疑BufferedReader方法會快得多......
這個想法; - /我想寫一個最簡單的例子。我想知道速度差異會是什么?
BufferedReader在這里并不過分。這個答案中的代碼將非常慢 - FileReader.read()將從文件中一次拉出一個字符。
答案是這里給出的'戲劇性'例子java.sun.com/developer/technicalArticles/Programming/PerfTuning
我在我的盒子上測量它,Jon Skeet是對的,差異很大。我在答案中添加了測量值。
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的java中获取文件总行数_关于java:如何以有效的方式获取文件中的行数?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 谈跨平台C++动态连接库的实现
- 下一篇: 学VBSCRIPT从学起