วิธีการอ่านไฟล์ทั้งหมดไปยังสตริงโดยใช้ C #?


215

วิธีที่เร็วที่สุดในการอ่านไฟล์ข้อความในตัวแปรสตริงคืออะไร?

ฉันเข้าใจว่าสามารถทำได้หลายวิธีเช่นอ่านแต่ละไบต์แล้วแปลงเป็นสตริง ฉันกำลังมองหาวิธีที่มีการเข้ารหัสน้อยที่สุด


คำตอบ:


373

เกี่ยวกับFile.ReadAllText:

string contents = File.ReadAllText(@"C:\temp\test.txt");

3
ไม่ใช่ฟังก์ชั่นที่ดีที่สุดในการใช้งาน ดังที่Devendra D. Chavanชี้ให้เห็นในคำตอบเขาStreamReader.ReadToEndมีประสิทธิภาพมากกว่า
Owen Blacker

40
@OwenBlacker มันขึ้นอยู่กับว่า "เร็วที่สุด" หมายถึง "เวลาน้อยที่สุดในการดำเนินการ" หรือ "เวลาน้อยที่สุดที่จะเข้าใจ"
bonh

2
File.ReadAllText เป็นหนึ่งในวิธีที่ง่ายที่สุดที่จะใช้ แต่เป็น "Devendra D. Chavan" ชี้ให้เห็นมันไม่ได้เร็วที่สุด ดังนั้นหากคุณกำลังอ่านไฟล์ขนาดเล็กมันจะเป็นทางเลือกที่ดีกว่าในการใช้ File.ReadAllText.it จริง ๆ แล้วขึ้นอยู่กับขนาดไฟล์ที่คุณกำลังอ่าน
มานะ

หากต้องการอ่านจากเซิร์ฟเวอร์ให้ตรวจสอบสิ่งนี้หวังว่าจะช่วยใครบางคน
shaijut

1
@OwenBlacker - คุณแน่ใจเหรอ? ดัชนีแสดงให้เห็นว่าจะมีประสิทธิภาพมากกว่าStreamReader.ReadToEnd ReadAllLinesซึ่งคาดว่าจะเป็นในขณะที่หลังยังแยกข้อความออกเป็นเส้น แต่เรากำลังพูดถึงวิธีการที่แตกต่างกัน, ReadAllText. คำตอบที่คุณพูดถึงแสดงให้เห็นว่าReadAllTextเพิ่งโทรStreamReader.ReadToEndภายใน
Ed Avis

170

การเปรียบเทียบเกณฑ์มาตรฐานของFile.ReadAllLinesvs StreamReader ReadLineจากการจัดการไฟล์ C #

เปรียบเทียบการอ่านไฟล์

ผล. StreamReader เร็วกว่ามากสำหรับไฟล์ขนาดใหญ่ที่มี 10,000 บรรทัด แต่ความแตกต่างของไฟล์ขนาดเล็กนั้นเล็กน้อย เช่นเคยวางแผนสำหรับขนาดไฟล์ที่แตกต่างกันและใช้ File.ReadAllLines เฉพาะเมื่อประสิทธิภาพไม่สำคัญ


วิธีการของ StreamReader

ในขณะที่File.ReadAllTextคนอื่นแนะนำวิธีการคุณสามารถลองได้เร็วขึ้น (ฉันไม่ได้ทดสอบผลกระทบเชิงปริมาณในเชิงปริมาณ แต่ดูเหมือนจะเร็วกว่าFile.ReadAllText(ดูการเปรียบเทียบด้านล่าง)) ความแตกต่างของ ประสิทธิภาพจะปรากฏเฉพาะในกรณีของไฟล์ขนาดใหญ่เท่านั้น

string readContents;
using (StreamReader streamReader = new StreamReader(path, Encoding.UTF8))
{
     readContents = streamReader.ReadToEnd();
}


เปรียบเทียบ File.Readxxx () vs StreamReader.Readxxx ()

การดูรหัสบ่งชี้ผ่านILSpyฉันได้พบสิ่งต่อไปนี้เกี่ยวกับFile.ReadAllLines, File.ReadAllText.

  • File.ReadAllText - ใช้StreamReader.ReadToEndภายใน
  • File.ReadAllLines - ใช้StreamReader.ReadLineภายในด้วยค่าใช้จ่ายเพิ่มเติมของการสร้างList<string>เพื่อส่งคืนเป็นบรรทัดการอ่านและวนซ้ำจนถึงจุดสิ้นสุดของไฟล์


ดังนั้นทั้งวิธีการที่เป็นเพิ่มเติมชั้นของความสะดวกสบายStreamReaderสร้างขึ้นบน นี่คือหลักฐานที่ชัดเจนของวิธีการ

File.ReadAllText() การดำเนินการตามที่ decompiled โดย ILSpy

public static string ReadAllText(string path)
{
    if (path == null)
    {
        throw new ArgumentNullException("path");
    }
    if (path.Length == 0)
    {
        throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
    }
    return File.InternalReadAllText(path, Encoding.UTF8);
}   

private static string InternalReadAllText(string path, Encoding encoding)
{
    string result;
    using (StreamReader streamReader = new StreamReader(path, encoding))
    {
        result = streamReader.ReadToEnd();
    }
    return result;
}

2
คุณเปรียบเทียบกับFile.ReadAllTextหรือไม่?
marc_s

2
ILSpy แสดงให้เห็นว่าเป็นเพียงเสื้อคลุมมากกว่าFile.ReadAllText() ฉันเดาว่าเพิ่มเติมชั้นควรดำเนินการช้ากว่าเล็กน้อยStreamReader.ReadToEnd() StreamReader.ReadToEnd()
Devendra D. Chavan

คำตอบที่ดี บางทีคำอธิบายเล็กน้อยสำหรับผู้ที่กำลังมองหาการแก้ไข แต่สมควรได้รับคะแนนอย่างน้อยที่สุดเท่าที่เป็นคำตอบที่เลือก
Sandy Gifford

@Devendra D. Chavan: Offtopic แต่ฉันจะหาข้อมูลอ้างอิงหรือเอกสารสำหรับ ILSpy ได้ที่ไหน
Viral Jain

1
นอกจากนี้คุณยังสามารถค้นหารหัสที่นี่: referencesource.microsoft.com/#mscorlib/system/io/... สิ่งที่ฉันไม่ได้รับคือเหตุผลที่มีความแตกต่างอย่างมีนัยสำคัญนี้ในความเร็วถ้าReadAllTextเป็นเพียงเสื้อคลุมสำหรับstreamReader.ReadToEnd();?
Olivier Jacot-Descombes


6

ลองดูที่File.ReadAllText ()วิธีการ

ข้อสังเกตที่สำคัญบางประการ:

วิธีนี้จะเปิดไฟล์อ่านแต่ละบรรทัดของไฟล์แล้วเพิ่มแต่ละบรรทัดเป็นองค์ประกอบของสตริง จากนั้นจะปิดไฟล์ บรรทัดถูกกำหนดเป็นลำดับของอักขระตามด้วย carriage return ('\ r'), line feed ('\ n') หรือ carriage return ในทันทีตามด้วย feed line สตริงผลลัพธ์ไม่ประกอบด้วยการขึ้นบรรทัดใหม่และ / หรือการป้อนบรรทัด

วิธีนี้จะพยายามตรวจจับการเข้ารหัสไฟล์โดยอัตโนมัติตามสถานะของเครื่องหมายคำสั่งซื้อไบต์ รูปแบบการเข้ารหัสสามารถตรวจพบ UTF-8 และ UTF-32 (ทั้งใหญ่และเล็ก)

ใช้เมธอด ReadAllText (สตริง, การเข้ารหัส) เกินพิกัดเมื่ออ่านไฟล์ที่อาจมีข้อความที่นำเข้าเนื่องจากอักขระที่ไม่รู้จักอาจอ่านไม่ถูกต้อง

ตัวจัดการไฟล์ถูกรับประกันว่าจะปิดโดยวิธีนี้แม้ว่าจะมีข้อยกเว้นเกิดขึ้น


6

string text = File.ReadAllText("Path");คุณมีข้อความทั้งหมดในตัวแปรสตริงเดียว หากคุณต้องการแต่ละบรรทัดคุณสามารถใช้สิ่งนี้:

string[] lines = File.ReadAllLines("Path");


4

@Cris ขอโทษนี่คือคำพูด MSDN Microsoft

ระเบียบวิธี

ในการทดลองนี้จะทำการเปรียบเทียบสองคลาส StreamReaderและFileStreamระดับจะถูกนำไปอ่านแฟ้มที่สองของ 10K และ 200K ในสิ่งทั้งปวงจากไดเรกทอรีแอพลิเคชัน

StreamReader (VB.NET)

sr = New StreamReader(strFileName)
Do
  line = sr.ReadLine()
Loop Until line Is Nothing
sr.Close()

FileStream (VB.NET)

Dim fs As FileStream
Dim temp As UTF8Encoding = New UTF8Encoding(True)
Dim b(1024) As Byte
fs = File.OpenRead(strFileName)
Do While fs.Read(b, 0, b.Length) > 0
    temp.GetString(b, 0, b.Length)
Loop
fs.Close()

ผลลัพธ์

ป้อนคำอธิบายรูปภาพที่นี่

FileStreamเห็นได้ชัดว่าเร็วขึ้นในการทดสอบนี้ ใช้เวลาเพิ่มอีก 50% ในStreamReaderการอ่านไฟล์ขนาดเล็ก สำหรับไฟล์ขนาดใหญ่ใช้เวลาเพิ่มขึ้น 27%

StreamReaderกำลังมองหาการแบ่งบรรทัดโดยเฉพาะในขณะที่FileStreamไม่ บัญชีนี้จะใช้เวลาพิเศษ

ข้อเสนอแนะ

แอปพลิเคชันที่ต้องทำกับส่วนของข้อมูลอาจมีการแยกวิเคราะห์เพิ่มเติมที่จะต้องใช้เวลาในการประมวลผลเพิ่มเติม พิจารณาสถานการณ์ที่ไฟล์มีคอลัมน์ของข้อมูลและCR/LFคั่นด้วยแถว สิ่งนี้StreamReaderจะทำงานในบรรทัดของข้อความที่ต้องการค้นหาCR/LFจากนั้นแอปพลิเคชันจะทำการแยกวิเคราะห์เพิ่มเติมเพื่อค้นหาตำแหน่งของข้อมูลที่เฉพาะเจาะจง (คุณคิดว่า String สตริงย่อยมาโดยไม่มีราคาหรือไม่)

ในทางกลับกันการFileStreamอ่านข้อมูลเป็นกลุ่มและผู้พัฒนาเชิงรุกสามารถเขียนตรรกะเพิ่มเติมเล็กน้อยเพื่อใช้สตรีมเพื่อผลประโยชน์ของเขา หากข้อมูลที่ต้องการอยู่ในตำแหน่งที่เฉพาะเจาะจงในไฟล์นี่จะเป็นวิธีที่แน่นอนในการลดการใช้หน่วยความจำ

FileStream เป็นกลไกที่ดีกว่าสำหรับความเร็ว แต่จะใช้ตรรกะมากกว่า


แต่เกี่ยวกับStreamReader.ReadToEndอะไร
Owen Blacker

3

วิธีที่เร็วที่สุดความหมายที่ดีที่สุดที่มีรหัส C # น้อยที่สุดน่าจะเป็นสิ่งนี้:

string readText = System.IO.File.ReadAllText(path);

3

หากคุณต้องการเลือกไฟล์จากโฟลเดอร์ Bin ของแอปพลิเคชันคุณสามารถลองทำตามและอย่าลืมจัดการข้อยกเว้น

string content = File.ReadAllText(Path.Combine(System.IO.Directory.GetCurrentDirectory(), @"FilesFolder\Sample.txt"));

3

คุณสามารถใช้ได้ :

 public static void ReadFileToEnd()
{
    try
    {
    //provide to reader your complete text file
        using (StreamReader sr = new StreamReader("TestFile.txt"))
        {
            String line = sr.ReadToEnd();
            Console.WriteLine(line);
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("The file could not be read:");
        Console.WriteLine(e.Message);
    }
}


2

สำหรับ noobs ออกมีผู้ที่พบสิ่งนี้สนุกและน่าสนใจวิธีที่เร็วที่สุดในการอ่านไฟล์ทั้งหมดเป็นสตริงในกรณีส่วนใหญ่ ( ตามมาตรฐานเหล่านี้ ) โดยต่อไปนี้:

using (StreamReader sr = File.OpenText(fileName))
{
        string s = sr.ReadToEnd();
}
//you then have to process the string

อย่างไรก็ตามการอ่านไฟล์ข้อความโดยรวมที่เร็วที่สุดคือ:

using (StreamReader sr = File.OpenText(fileName))
{
        string s = String.Empty;
        while ((s = sr.ReadLine()) != null)
        {
               //do what you have to here
        }
}

วางกับเทคนิคอื่น ๆ หลายมันชนะเวลาส่วนใหญ่รวมถึงกับ BufferedReader


ฉันรู้ว่าความคิดเห็นมาช้าแล้ว แต่สับสนเล็กน้อยในการวัดประสิทธิภาพของคุณที่นี่และในหน้าเชื่อมโยง ดูเหมือนว่าจะเป็นการทดสอบความเร็วในการอ่านเท่านั้นและไม่โหลดลงในทั้งสตริง ข้อมูลโค้ดที่สองกำลังอ่านบรรทัดในเวลาหนึ่งและไม่ทำการต่อท้ายดังนั้น "ทำสิ่งที่คุณต้องทำที่นี่" จะต้องมีตัวสร้างสตริงหรือสตริงเพื่อเก็บข้อมูล ณ จุดนี้หน่วยความจำที่ใช้ในการเพิ่มข้อมูลมากขึ้นจะเปลี่ยนผลการทดสอบ ดังนั้น s จะมีขนาดเท่ากันโดยสมมติว่าเป็นไฟล์ที่มีความกว้างคงที่ดังนั้นหน่วยความจำจะถูกตั้งค่าสำหรับขนาดของเส้นและข้อมูลไม่จำเป็นต้องคัดลอกไปยังหน่วยความจำใหม่
Charles Byrne

2

คุณสามารถใช้สิ่งนี้

public static string ReadFileAndFetchStringInSingleLine(string file)
    {
        StringBuilder sb;
        try
        {
            sb = new StringBuilder();
            using (FileStream fs = File.Open(file, FileMode.Open))
            {
                using (BufferedStream bs = new BufferedStream(fs))
                {
                    using (StreamReader sr = new StreamReader(bs))
                    {
                        string str;
                        while ((str = sr.ReadLine()) != null)
                        {
                            sb.Append(str);
                        }
                    }
                }
            }
            return sb.ToString();
        }
        catch (Exception ex)
        {
            return "";
        }
    }

หวังว่านี่จะช่วยคุณได้


0

คุณสามารถอ่านข้อความจากไฟล์ข้อความในสตริงได้ดังนี้

string str = "";
StreamReader sr = new StreamReader(Application.StartupPath + "\\Sample.txt");
while(sr.Peek() != -1)
{
  str = str + sr.ReadLine();
}

0
public partial class Testfile : System.Web.UI.Page
{
    public delegate void DelegateWriteToDB(string Inputstring);
    protected void Page_Load(object sender, EventArgs e)
    {
        getcontent(@"C:\Working\Teradata\New folder");
    }

      private void SendDataToDB(string data)
    {
        //InsertIntoData
          //Provider=SQLNCLI10.1;Integrated Security=SSPI;Persist Security Info=False;User ID="";Initial Catalog=kannan;Data Source=jaya;
        SqlConnection Conn = new SqlConnection("Data Source=aras;Initial Catalog=kannan;Integrated Security=true;");
        SqlCommand cmd = new SqlCommand();
        cmd.Connection = Conn;
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = "insert into test_file values('"+data+"')";
        cmd.Connection.Open();
        cmd.ExecuteNonQuery();
        cmd.Connection.Close();
    }

      private void getcontent(string path)
      {
          string[] files;
          files = Directory.GetFiles(path, "*.txt");
          StringBuilder sbData = new StringBuilder();
          StringBuilder sbErrorData = new StringBuilder();
          Testfile df = new Testfile();
          DelegateWriteToDB objDelegate = new DelegateWriteToDB(df.SendDataToDB);
          //dt.Columns.Add("Data",Type.GetType("System.String"));


          foreach (string file in files)
          {
              using (StreamReader sr = new StreamReader(file))
              {
                  String line;
                  int linelength;
                  string space = string.Empty;

                  // Read and display lines from the file until the end of 
                  // the file is reached.
                  while ((line = sr.ReadLine()) != null)
                  {
                      linelength = line.Length;
                      switch (linelength)
                      {
                          case 5:
                              space = "     ";
                              break;

                      }
                      if (linelength == 5)
                      {
                          IAsyncResult ObjAsynch = objDelegate.BeginInvoke(line + space, null, null);
                      }
                      else if (linelength == 10)
                      {
                          IAsyncResult ObjAsynch = objDelegate.BeginInvoke(line , null, null);
                      }

                  }
              }
          }
      }
    }

0

ฉันทำการเปรียบเทียบระหว่าง ReadAllText และ StreamBuffer สำหรับ 2Mb csv และดูเหมือนว่าความแตกต่างนั้นค่อนข้างเล็ก แต่ ReadAllText ดูเหมือนจะยกระดับขึ้นจากเวลาที่ทำหน้าที่ให้เสร็จสมบูรณ์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.