Jak odczytać cały plik do ciągu za pomocą C #?

214

Jaki jest najszybszy sposób wczytania pliku tekstowego do zmiennej łańcuchowej?

Rozumiem, że można to zrobić na kilka sposobów, na przykład czytać poszczególne bajty, a następnie konwertować je na ciąg. Szukałem metody z minimalnym kodowaniem.

Shamim Hafiz
źródło
Sprawdź ten stackoverflow.com/questions/2855335/…
Sandeep GB

Odpowiedzi:

373

Co powiesz na File.ReadAllText:

string contents = File.ReadAllText(@"C:\temp\test.txt");
marc_s
źródło
3
Nie jest to jednak najlepsza funkcja do użycia. Jak wskazuje Devendra D. Chavan w swojej odpowiedzi, StreamReader.ReadToEndjest bardziej wydajny.
Owen Blacker
40
@OwenBlacker Zależy to od tego, czy „najszybszy” oznacza „najmniej czasu na wykonanie” czy „najmniej czasu na zrozumienie”.
bonh
2
File.ReadAllText jest zdecydowanie najłatwiejszy w użyciu, ale jak zauważa „Devendra D. Chavan”, nie jest najszybszy. Więc jeśli czytasz małe pliki, lepszym wyborem byłoby użycie File.ReadAllText.it naprawdę zależy od tego, jak duże są pliki tekstowe, które czytasz.
Mana,
Aby odczytać z serwera, sprawdź to , mam nadzieję, że ktoś komuś pomoże.
shaijut
1
@OwenBlacker - jesteś pewien? Benchmark pokazuje, że StreamReader.ReadToEndjest bardziej wydajny niż ReadAllLines. Tego należy się spodziewać, ponieważ ten ostatni dzieli również tekst na linie. Ale mówimy o innej metodzie ReadAllText. Rzeczywiście, wspomniana odpowiedź pokazuje, że ReadAllTextpo prostu dzwonisz StreamReader.ReadToEndwewnętrznie.
Ed Avis,
169

Porównanie testów porównawczych File.ReadAllLinesvs StreamReader ReadLinez obsługą plików C #

Porównanie odczytu plików

Wyniki StreamReader jest znacznie szybszy dla dużych plików z ponad 10 000 linii, ale różnica dla mniejszych plików jest znikoma. Jak zawsze, planuj różne rozmiary plików i używaj File.ReadAllLines tylko wtedy, gdy wydajność nie jest krytyczna.


Podejście StreamReader

Jak File.ReadAllTextinni sugerują to podejście, możesz także spróbować szybciej (nie testowałem ilościowo wpływu na wydajność, ale wydaje się, że jest szybszy niż File.ReadAllText(patrz porównanie poniżej)). Różnica w wydajności będzie widoczny tylko w przypadku większych plików chociaż.

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


Porównanie File.Readxxx () vs StreamReader.Readxxx ()

Przeglądanie kodu wskazującego przez ILSpy Znalazłem następujące informacje File.ReadAllLines, File.ReadAllText.

  • File.ReadAllText - Wykorzystuje StreamReader.ReadToEndwewnętrznie
  • File.ReadAllLines - Używa również StreamReader.ReadLinewewnętrznie z dodatkowym narzutem związanym z tworzeniem List<string>powrotu jako linii odczytu i zapętlaniem do końca pliku.


Więc obie metody są dodatkową warstwą wygody zbudowany na szczycie StreamReader. Jest to widoczne w indykatywnej treści metody.

File.ReadAllText() implementacja zdekompilowana przez 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;
}
Devendra D. Chavan
źródło
2
Czy ty też porównywałeś File.ReadAllText?
marc_s
2
ILSpy sugeruje, że File.ReadAllText()jest to po prostu opakowanie StreamReader.ReadToEnd(). Zgaduję, że dodatkowa warstwa powinna działać nieco wolniej niż StreamReader.ReadToEnd().
Devendra D. Chavan
Świetna odpowiedź. Być może trochę wyjaśnienia dla tych, którzy szukają poprawki, ale zasługuje ona na co najmniej tyle głosów, ile wybrana odpowiedź.
Sandy Gifford,
@Devendra D. Chavan: Offtopic, ale gdzie mogę znaleźć referencje lub dokumentację dla ILSpy?
Viral Jain
1
Możesz także znaleźć kod tutaj: referenceource.microsoft.com/#mscorlib/system/io/… . Nie rozumiem, dlaczego jest tak znacząca różnica prędkości, jeśli ReadAllTextjest to tylko opakowanie streamReader.ReadToEnd();?
Olivier Jacot-Descombes
6

Spójrz na metodę File.ReadAllText ()

Kilka ważnych uwag:

Ta metoda otwiera plik, odczytuje każdą linię pliku, a następnie dodaje każdą linię jako element łańcucha. Następnie zamyka plik. Linia jest zdefiniowana jako sekwencja znaków, po której następuje powrót karetki ('\ r'), znak końca linii ('\ n') lub znak powrotu karetki, po którym następuje znak linii. Powstały ciąg nie zawiera zakończenia powrotu karetki i / lub przesunięcia wiersza.

Ta metoda próbuje automatycznie wykryć kodowanie pliku na podstawie obecności znaków kolejności bajtów. Formaty kodowania UTF-8 i UTF-32 (zarówno big-endian, jak i little-endian) mogą zostać wykryte.

Użyj przeciążenia metody ReadAllText (String, Encoding) podczas odczytywania plików, które mogą zawierać zaimportowany tekst, ponieważ nierozpoznane znaki mogą nie zostać poprawnie odczytane.

Ta metoda gwarantuje, że uchwyt pliku zostanie zamknięty, nawet jeśli zgłoszone zostaną wyjątki

sll
źródło
6

string text = File.ReadAllText("Path");masz cały tekst w jednej zmiennej łańcuchowej. Jeśli potrzebujesz każdej linii osobno, możesz użyć tego:

string[] lines = File.ReadAllLines("Path");
Dilshod
źródło
4
System.IO.StreamReader myFile =
   new System.IO.StreamReader("c:\\test.txt");
string myString = myFile.ReadToEnd();
Maxim V. Pavlov
źródło
4

@Cris przepraszam. To jest cytat MSDN Microsoft

Metodologia

W tym eksperymencie porównane zostaną dwie klasy. Klasa StreamReaderi FileStreamzostanie skierowana do odczytu dwóch plików 10K i 200K w całości z katalogu aplikacji.

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()

Wynik

wprowadź opis zdjęcia tutaj

FileStreamjest oczywiście szybszy w tym teście. StreamReaderPrzeczytanie małego pliku zajmuje dodatkowe 50% więcej czasu . W przypadku dużego pliku zajęło to dodatkowe 27% czasu.

StreamReaderszczególnie szuka podziałów linii, podczas gdy FileStreamnie. To będzie stanowiło część dodatkowego czasu.

Rekomendacje

W zależności od tego, co aplikacja musi zrobić z sekcją danych, może wystąpić dodatkowe przetwarzanie, które będzie wymagało dodatkowego czasu przetwarzania. Rozważ scenariusz, w którym plik zawiera kolumny danych, a wiersze są CR/LFrozdzielane. Spowoduje StreamReaderto wyszukanie wiersza tekstu CR/LF, a następnie aplikacja wykona dodatkowe analizowanie w poszukiwaniu określonej lokalizacji danych. (Myślałeś, że String. SubString jest dostępny bez ceny?)

Z drugiej strony dane są FileStreamodczytywane we fragmentach, a proaktywny programista mógłby napisać nieco więcej logiki, aby wykorzystać strumień na swoją korzyść. Jeśli potrzebne dane znajdują się w określonych pozycjach w pliku, jest to z pewnością odpowiednia droga, ponieważ zmniejsza zużycie pamięci.

FileStream jest lepszym mechanizmem prędkości, ale wymaga większej logiki.

MinhVuong
źródło
Ale co z StreamReader.ReadToEnd?
Owen Blacker
3

cóż, najszybszym sposobem oznaczania przy możliwie najmniejszym kodzie C # jest prawdopodobnie ten:

string readText = System.IO.File.ReadAllText(path);
Davide Piras
źródło
3

jeśli chcesz wybrać plik z folderu Bin aplikacji, możesz spróbować śledzić i nie zapomnieć o obsłudze wyjątków.

string content = File.ReadAllText(Path.Combine(System.IO.Directory.GetCurrentDirectory(), @"FilesFolder\Sample.txt"));
Głębiny
źródło
3

możesz użyć :

 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);
    }
}
Erwin Draconis
źródło
2
string content = System.IO.File.ReadAllText( @"C:\file.txt" );
Paul Mitchell
źródło
2

Dla noobów, którzy uważają to za zabawne i interesujące, najszybszy sposób na odczytanie całego pliku w ciągu w większości przypadków ( zgodnie z tymi testami ) jest następujący:

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

Jednak absolutnie najszybszy odczyt pliku tekstowego wydaje się następujący:

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

Przeciwstawiony kilku innym technikom , przez większość czasu wygrywał, w tym przeciwko BufferedReader.


źródło
Komentarz jest spóźniony, wiem, ale trochę zmieszany w testach porównawczych tutaj i na połączonej stronie. Wygląda na to, że testuje tylko prędkości odczytu i nie ładuje się do całego ciągu. Drugi fragment kodu odczytuje wiersz na raz i nie wykonuje żadnych dopisów, więc „zrób to, co musisz tutaj” musiałby mieć konstruktor ciągów lub ciąg do przechowywania danych. W tym momencie pamięć użyta do dodania większej ilości danych zmieni wyniki testu. Więc s będzie zwykle tego samego rozmiaru, zakładając plik o stałej szerokości, więc pamięć zostanie ustawiona na rozmiar linii i dane nie będą musiały być kopiowane do nowej pamięci.
Charles Byrne,
2

Możesz użyć w ten sposób

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 "";
        }
    }

Mam nadzieję, że to ci pomoże.

Amit Kumawat
źródło
0

możesz przeczytać tekst z pliku tekstowego do łańcucha w następujący sposób

string str = "";
StreamReader sr = new StreamReader(Application.StartupPath + "\\Sample.txt");
while(sr.Peek() != -1)
{
  str = str + sr.ReadLine();
}
Sai Kalyan Kumar Akshinthala
źródło
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);
                      }

                  }
              }
          }
      }
    }
SÓJKA
źródło
0

Dokonałem porównania między ReadAllText i StreamBuffer dla csv 2Mb i wydawało się, że różnica była dość niewielka, ale ReadAllText wydawał się przewodzić od czasów wymaganych do ukończenia funkcji.

Hatitye Chindove
źródło