มีวิธีง่ายๆในการกำหนดจำนวนบรรทัดภายในไฟล์ข้อความโดยทางโปรแกรมหรือไม่?
มีวิธีง่ายๆในการกำหนดจำนวนบรรทัดภายในไฟล์ข้อความโดยทางโปรแกรมหรือไม่?
คำตอบ:
การแก้ไขล่าช้าอย่างจริงจัง: หากคุณใช้. NET 4.0 หรือใหม่กว่า
File
ชั้นจะมีใหม่วิธีที่เฉื่อยชาระบุเส้นมากกว่าละโมบอ่านพวกเขาทั้งหมดลงในอาร์เรย์เช่นReadLines
ReadAllLines
ดังนั้นตอนนี้คุณสามารถมีทั้งประสิทธิภาพและความกระชับด้วย:
var lineCount = File.ReadLines(@"C:\file.txt").Count();
คำตอบเดิม
หากคุณไม่ใส่ใจเรื่องประสิทธิภาพคุณสามารถเขียน:
var lineCount = File.ReadAllLines(@"C:\file.txt").Length;
สำหรับวิธีที่มีประสิทธิภาพมากขึ้นคุณสามารถทำได้:
var lineCount = 0;
using (var reader = File.OpenText(@"C:\file.txt"))
{
while (reader.ReadLine() != null)
{
lineCount++;
}
}
แก้ไข: เพื่อตอบคำถามเกี่ยวกับประสิทธิภาพ
เหตุผลที่ฉันพูดที่สองมีประสิทธิภาพมากขึ้นคือเกี่ยวกับการใช้หน่วยความจำไม่จำเป็นต้องเพิ่มความเร็ว คนแรกที่โหลดเนื้อหาทั้งหมดของไฟล์ลงในอาร์เรย์ซึ่งหมายความว่ามันจะต้องจัดสรรหน่วยความจำอย่างน้อยเท่าขนาดของไฟล์ ครั้งที่สองจะวนรอบทีละหนึ่งบรรทัดเท่านั้นดังนั้นจึงไม่จำเป็นต้องจัดสรรหน่วยความจำมากกว่าหนึ่งบรรทัดในแต่ละครั้ง นี่ไม่ใช่สิ่งสำคัญสำหรับไฟล์ขนาดเล็ก แต่สำหรับไฟล์ที่มีขนาดใหญ่กว่าอาจเป็นปัญหา (หากคุณลองและค้นหาจำนวนบรรทัดในไฟล์ 4GB บนระบบ 32 บิตตัวอย่างเช่นที่นั่นมีไม่เพียงพอ พื้นที่ที่อยู่โหมดผู้ใช้ในการจัดสรรอาร์เรย์ขนาดใหญ่นี้)
ในแง่ของความเร็วฉันไม่คิดว่ามันจะมีอะไรมากมาย เป็นไปได้ว่า ReadAllLines มีการเพิ่มประสิทธิภาพภายในบางอย่าง แต่ในทางกลับกันอาจต้องจัดสรรหน่วยความจำจำนวนมาก ฉันเดาว่า ReadAllLines อาจเร็วกว่าสำหรับไฟล์ขนาดเล็ก แต่ช้าลงอย่างมากสำหรับไฟล์ขนาดใหญ่ แม้ว่าวิธีเดียวที่จะบอกได้ก็คือการวัดด้วย Stopwatch หรือ Code Profiler
ReadLines().Count()
คุณจะต้องเพิ่ม a using System.Linq
ไปยังของคุณ ดูเหมือนว่าไม่ใช่เรื่องง่ายที่จะต้องมีการเพิ่มนั่นคือเหตุผลที่ฉันพูดถึงมัน หากคุณใช้ Visual Studio อาจเป็นไปได้ว่าการเพิ่มนี้จะดำเนินการให้คุณโดยอัตโนมัติ
ง่ายที่สุด:
int lines = File.ReadAllLines("myfile").Length;
สิ่งนี้จะใช้หน่วยความจำน้อยลง แต่อาจใช้เวลานานกว่า
int count = 0;
string line;
TextReader reader = new StreamReader("file.txt");
while ((line = reader.ReadLine()) != null)
{
count++;
}
reader.Close();
ถ้าง่ายคุณหมายถึงบรรทัดของรหัสที่ง่ายต่อการถอดรหัส แต่ไม่มีประสิทธิภาพต่อโอกาส?
string[] lines = System.IO.File.RealAllLines($filename);
int cnt = lines.Count();
นั่นอาจเป็นวิธีที่เร็วที่สุดในการรู้จำนวนบรรทัด
คุณสามารถทำได้ (ขึ้นอยู่กับว่าคุณกำลังบัฟเฟอร์อยู่หรือไม่)
#for large files
while (...reads into buffer){
string[] lines = Regex.Split(buffer,System.Enviorment.NewLine);
}
ยังมีอีกหลายวิธี แต่อย่างใดอย่างหนึ่งข้างต้นอาจเป็นสิ่งที่คุณจะไปด้วย
คุณสามารถอ่านได้อย่างรวดเร็วและเพิ่มตัวนับเพียงใช้วนซ้ำเพื่อเพิ่มโดยไม่ทำอะไรกับข้อความ
การอ่านไฟล์ในและโดยตัวของมันเองใช้เวลาพอสมควรการเก็บขยะผลลัพธ์เป็นปัญหาอื่นเมื่อคุณอ่านไฟล์ทั้งหมดเพื่อนับจำนวนอักขระขึ้นบรรทัดใหม่
เมื่อถึงจุดหนึ่งบางคนจะต้องอ่านตัวอักษรในไฟล์โดยไม่คำนึงว่าเฟรมเวิร์กนี้หรือว่าเป็นรหัสของคุณ ซึ่งหมายความว่าคุณต้องเปิดไฟล์และอ่านมันในหน่วยความจำหากไฟล์มีขนาดใหญ่ซึ่งอาจเป็นปัญหาเนื่องจากหน่วยความจำต้องรวบรวมขยะ
Nima Ara ทำการวิเคราะห์ที่ดีที่คุณอาจต้องคำนึงถึง
ต่อไปนี้เป็นวิธีแก้ไขปัญหาที่เสนอเนื่องจากจะอ่านอักขระได้ครั้งละ 4 ตัวนับจำนวนอักขระตัวป้อนบรรทัดและใช้ที่อยู่หน่วยความจำเดียวกันอีกครั้งเพื่อการเปรียบเทียบอักขระถัดไป
private const char CR = '\r';
private const char LF = '\n';
private const char NULL = (char)0;
public static long CountLinesMaybe(Stream stream)
{
Ensure.NotNull(stream, nameof(stream));
var lineCount = 0L;
var byteBuffer = new byte[1024 * 1024];
const int BytesAtTheTime = 4;
var detectedEOL = NULL;
var currentChar = NULL;
int bytesRead;
while ((bytesRead = stream.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
{
var i = 0;
for (; i <= bytesRead - BytesAtTheTime; i += BytesAtTheTime)
{
currentChar = (char)byteBuffer[i];
if (detectedEOL != NULL)
{
if (currentChar == detectedEOL) { lineCount++; }
currentChar = (char)byteBuffer[i + 1];
if (currentChar == detectedEOL) { lineCount++; }
currentChar = (char)byteBuffer[i + 2];
if (currentChar == detectedEOL) { lineCount++; }
currentChar = (char)byteBuffer[i + 3];
if (currentChar == detectedEOL) { lineCount++; }
}
else
{
if (currentChar == LF || currentChar == CR)
{
detectedEOL = currentChar;
lineCount++;
}
i -= BytesAtTheTime - 1;
}
}
for (; i < bytesRead; i++)
{
currentChar = (char)byteBuffer[i];
if (detectedEOL != NULL)
{
if (currentChar == detectedEOL) { lineCount++; }
}
else
{
if (currentChar == LF || currentChar == CR)
{
detectedEOL = currentChar;
lineCount++;
}
}
}
}
if (currentChar != LF && currentChar != CR && currentChar != NULL)
{
lineCount++;
}
return lineCount;
}
ด้านบนคุณจะเห็นว่าบรรทัดมีการอ่านหนึ่งอักขระในแต่ละครั้งพร้อมกับเฟรมเวิร์กพื้นฐานที่คุณต้องอ่านอักขระทั้งหมดเพื่อดูตัวดึงข้อมูลบรรทัด
หากคุณโพรไฟล์มันเป็นอ่าวนิมาคุณจะเห็นว่านี่เป็นวิธีที่รวดเร็วและมีประสิทธิภาพในการทำสิ่งนี้
นับการขึ้นบรรทัดใหม่ ฉันเชื่อในยูนิโค้ดพวกเขายังคงเป็น 0x000D และ 0x000A ตามลำดับ ด้วยวิธีนี้คุณจะมีประสิทธิภาพหรือไม่มีประสิทธิภาพเท่าที่คุณต้องการและตัดสินใจว่าคุณต้องรับมือกับตัวละครทั้งสองหรือไม่
ตัวเลือกที่ทำงานได้และตัวเลือกที่ฉันใช้เป็นการส่วนตัวคือการเพิ่มส่วนหัวของคุณเองในบรรทัดแรกของไฟล์ ฉันทำสิ่งนี้ในรูปแบบโมเดลที่กำหนดเองสำหรับเกมของฉัน โดยทั่วไปฉันมีเครื่องมือที่ปรับไฟล์. obj ให้เหมาะสมกำจัดอึที่ไม่ต้องการแปลงให้เป็นเลย์เอาต์ที่ดีขึ้นจากนั้นเขียนจำนวนบรรทัดใบหน้าบรรทัดฐานจุดยอดและพื้นผิว UV บน บรรทัดแรก ข้อมูลนั้นจะถูกใช้โดยบัฟเฟอร์อาร์เรย์ต่าง ๆ เมื่อโหลดโมเดล
สิ่งนี้มีประโยชน์เพราะคุณต้องวนลูปไฟล์เพียงครั้งเดียวเพื่อทำการโหลดแทนที่จะนับหนึ่งครั้งเพื่อนับบรรทัดและอีกครั้งเพื่ออ่านข้อมูลลงในบัฟเฟอร์ที่คุณสร้างขึ้น
try {
string path = args[0];
FileStream fh = new FileStream(path, FileMode.Open, FileAccess.Read);
int i;
string s = "";
while ((i = fh.ReadByte()) != -1)
s = s + (char)i;
//its for reading number of paragraphs
int count = 0;
for (int j = 0; j < s.Length - 1; j++) {
if (s.Substring(j, 1) == "\n")
count++;
}
Console.WriteLine("The total searches were :" + count);
fh.Close();
} catch(Exception ex) {
Console.WriteLine(ex.Message);
}