Wie lese ich eine ganze Datei mit C # in eine Zeichenfolge?

214

Was ist der schnellste Weg, um eine Textdatei in eine Zeichenfolgenvariable einzulesen?

Ich verstehe, dass dies auf verschiedene Arten geschehen kann, z. B. indem einzelne Bytes gelesen und dann in Zeichenfolgen konvertiert werden. Ich suchte nach einer Methode mit minimaler Codierung.

Shamim Hafiz
quelle
Überprüfen Sie diese stackoverflow.com/questions/2855335/…
Sandeep GB

Antworten:

373

Wie wäre es mit File.ReadAllText:

string contents = File.ReadAllText(@"C:\temp\test.txt");
marc_s
quelle
3
Nicht die beste Funktion. Wie Devendra D. Chavan in seiner Antwort betont, StreamReader.ReadToEndist effizienter.
Owen Blacker
40
@OwenBlacker Es hängt davon ab, ob "am schnellsten" "am wenigsten Zeit zum Ausführen" oder "am wenigsten Zeit zum Verstehen" bedeutet.
Bonh
2
File.ReadAllText ist definitiv am einfachsten zu verwenden, aber wie "Devendra D. Chavan" hervorhebt, ist es nicht der schnellste. Wenn Sie also kleine Dateien lesen, ist es besser, File.ReadAllText.it zu verwenden. Dies hängt wirklich davon ab, wie groß die Textdateien sind, die Sie lesen.
Mana
Um vom Server zu lesen, überprüfen Sie dies , Hoffnung hilft jemandem.
Shaijut
1
@OwenBlacker - bist du sicher? Der Benchmark zeigt, dass dies StreamReader.ReadToEndeffizienter ist als ReadAllLines. Was zu erwarten ist, da letztere den Text auch in Zeilen aufteilt. Wir sprechen aber von einer anderen Methode ReadAllText. In der Tat zeigt die Antwort, die Sie erwähnen, dass ReadAllTextnur StreamReader.ReadToEndintern angerufen wird.
Ed Avis
169

Ein Benchmark-Vergleich von File.ReadAllLinesvs StreamReader ReadLineaus C # -Dateibehandlung

Dateilesevergleich

Ergebnisse. StreamReader ist für große Dateien mit mehr als 10.000 Zeilen viel schneller, aber der Unterschied für kleinere Dateien ist vernachlässigbar. Planen Sie wie immer unterschiedliche Dateigrößen und verwenden Sie File.ReadAllLines nur, wenn die Leistung nicht kritisch ist.


StreamReader-Ansatz

Da der File.ReadAllTextAnsatz von anderen vorgeschlagen wurde, können Sie ihn auch schneller ausprobieren (ich habe die Auswirkungen auf die Leistung nicht quantitativ getestet, aber er scheint schneller zu sein als File.ReadAllText(siehe Vergleich unten)). Der Unterschied in der Leistung wird nur bei größeren Dateien jedoch sichtbar sein.

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


Vergleich von File.Readxxx () mit StreamReader.Readxxx ()

Beim Anzeigen des indikativen Codes über ILSpy habe ich Folgendes gefunden File.ReadAllLines: File.ReadAllText.

  • File.ReadAllText - Wird StreamReader.ReadToEndintern verwendet
  • File.ReadAllLines - Verwendet auch StreamReader.ReadLineintern mit dem zusätzlichen Aufwand, die List<string>als Lesezeilen zurückzugeben und bis zum Ende der Datei zu schleifen.


Beide Methoden sind also eine zusätzliche Komfortschicht, die darauf aufbaut StreamReader. Dies wird durch den indikativen Körper der Methode deutlich.

File.ReadAllText() Implementierung wie von ILSpy dekompiliert

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
quelle
2
Hast du auch mit verglichen File.ReadAllText?
marc_s
2
ILSpy schlägt vor, dass dies File.ReadAllText()einfach ein Wrapper ist StreamReader.ReadToEnd(). Ich vermute, dass die zusätzliche Ebene etwas langsamer als arbeiten sollte StreamReader.ReadToEnd().
Devendra D. Chavan
Gute Antwort. Vielleicht ein bisschen viel Erklärung für diejenigen, die nur nach dem Fix suchen, aber es verdient mindestens so viele Stimmen wie die gewählte Antwort.
Sandy Gifford
@ Devendra D. Chavan: Offtopic, aber wo finde ich Referenzen oder Dokumentationen für ILSpy?
Viral Jain
1
Den Code finden Sie auch hier: referencesource.microsoft.com/#mscorlib/system/io/… . Was ich nicht verstehe, ist, warum es diesen signifikanten Geschwindigkeitsunterschied gibt, wenn ReadAllTextes nur ein Wrapper ist streamReader.ReadToEnd();?
Olivier Jacot-Descombes
6

Schauen Sie sich File.ReadAllText () an -Methode an

Einige wichtige Bemerkungen:

Diese Methode öffnet eine Datei, liest jede Zeile der Datei und fügt dann jede Zeile als Element einer Zeichenfolge hinzu. Anschließend wird die Datei geschlossen. Eine Zeile ist definiert als eine Folge von Zeichen, gefolgt von einem Wagenrücklauf ('\ r'), einem Zeilenvorschub ('\ n') oder einem Wagenrücklauf, unmittelbar gefolgt von einem Zeilenvorschub. Die resultierende Zeichenfolge enthält nicht den abschließenden Wagenrücklauf und / oder den Zeilenvorschub.

Diese Methode versucht, die Codierung einer Datei basierend auf dem Vorhandensein von Byte-Ordnungsmarkierungen automatisch zu erkennen. Die Codierungsformate UTF-8 und UTF-32 (sowohl Big-Endian als auch Little-Endian) können erkannt werden.

Verwenden Sie beim Lesen von Dateien, die möglicherweise importierten Text enthalten, die Überladung der ReadAllText-Methode (String, Encoding), da nicht erkannte Zeichen möglicherweise nicht richtig gelesen werden.

Das Dateihandle wird durch diese Methode garantiert geschlossen, auch wenn Ausnahmen ausgelöst werden

sll
quelle
6

string text = File.ReadAllText("Path");Sie haben den gesamten Text in einer Zeichenfolgenvariablen. Wenn Sie jede Zeile einzeln benötigen, können Sie Folgendes verwenden:

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

@Cris sorry. Dies ist ein Zitat MSDN Microsoft

Methodik

In diesem Experiment werden zwei Klassen verglichen. Die StreamReaderund die FileStreamKlasse werden angewiesen, zwei Dateien mit 10 KB und 200 KB in ihrer Gesamtheit aus dem Anwendungsverzeichnis zu lesen.

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

Ergebnis

Geben Sie hier die Bildbeschreibung ein

FileStreamist in diesem Test offensichtlich schneller. Das StreamReaderLesen der kleinen Datei dauert zusätzlich 50% länger . Für die große Datei wurden zusätzlich 27% der Zeit benötigt.

StreamReadersucht gezielt nach Zeilenumbrüchen, FileStreamtut dies aber nicht. Dies wird einen Teil der zusätzlichen Zeit ausmachen.

Empfehlungen

Abhängig davon, was die Anwendung mit einem Datenabschnitt tun muss, kann es zu einer zusätzlichen Analyse kommen, die zusätzliche Verarbeitungszeit erfordert. Stellen Sie sich ein Szenario vor, in dem eine Datei Datenspalten enthält und die Zeilen CR/LFbegrenzt sind. Das StreamReaderwürde in der Textzeile nach dem suchenCR/LF und dann würde die Anwendung zusätzliche Analyse durchführen, um nach einem bestimmten Speicherort für Daten zu suchen. (Hast du gedacht, String. SubString kommt ohne Preis?)

Auf der anderen Seite FileStreamliest das die Daten in Blöcken und ein proaktiver Entwickler könnte etwas mehr Logik schreiben, um den Stream zu seinem Vorteil zu nutzen. Wenn sich die benötigten Daten an bestimmten Stellen in der Datei befinden, ist dies sicherlich der richtige Weg, da dadurch die Speichernutzung gering gehalten wird.

FileStream ist der bessere Mechanismus für die Geschwindigkeit, erfordert aber mehr Logik.

MinhVuong
quelle
Aber was ist mit StreamReader.ReadToEnd?
Owen Blacker
3

Nun, der schnellste Weg mit dem geringstmöglichen C # -Code ist wahrscheinlich der folgende:

string readText = System.IO.File.ReadAllText(path);
Davide Piras
quelle
3

Wenn Sie eine Datei aus dem Bin-Ordner der Anwendung auswählen möchten, können Sie Folgendes versuchen und die Ausnahmebehandlung nicht vergessen.

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

Sie können verwenden:

 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
quelle
2
string content = System.IO.File.ReadAllText( @"C:\file.txt" );
Paul Mitchell
quelle
2

Für die Noobs da draußen, die dieses Zeug lustig und interessant finden, ist der schnellste Weg, eine ganze Datei in einen String zu lesen, in den meisten Fällen ( gemäß diesen Benchmarks ):

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

Das absolut schnellste Lesen einer Textdatei insgesamt scheint jedoch das Folgende zu sein:

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

Gegen mehrere andere Techniken hat es die meiste Zeit gewonnen, auch gegen den BufferedReader.


quelle
Kommentar ist spät, ich weiß, aber ein wenig verwirrt über Ihre Benchmarks hier und auf der verlinkten Seite. Es scheint nur Lesegeschwindigkeiten zu testen und nicht in eine ganze Zeichenfolge zu laden. Das zweite Code-Snippet liest jeweils eine Zeile und führt keine Anhänge durch, sodass für das "Tun, was Sie hier tun müssen" ein String-Builder oder eine Zeichenfolge erforderlich ist, um die Daten zu speichern. Zu diesem Zeitpunkt würde der Speicher, der zum Hinzufügen weiterer Daten verwendet wird, die Testergebnisse ändern. Daher hat s normalerweise die gleiche Größe, wenn eine Datei mit fester Breite angenommen wird, sodass der Speicher auf die Größe einer Zeile eingestellt wird und die Daten nicht in den neuen Speicher kopiert werden müssen.
Charles Byrne
2

Sie können so verwenden

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

Hoffe das wird dir helfen.

Amit Kumawat
quelle
0

Sie können einen Text aus einer Textdatei wie folgt in eine Zeichenfolge einlesen

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

                  }
              }
          }
      }
    }
JAY
quelle
0

Ich habe einen Vergleich zwischen einem ReadAllText und einem StreamBuffer für eine 2-MB-CSV durchgeführt, und es schien, dass der Unterschied recht gering war, aber ReadAllText schien die Oberhand von den Zeiten zu übernehmen, die für die Ausführung von Funktionen benötigt wurden.

Hatitye Chindove
quelle