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.
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.
Odpowiedzi:
Co powiesz na File.ReadAllText
:
string contents = File.ReadAllText(@"C:\temp\test.txt");
StreamReader.ReadToEnd
jest bardziej wydajny.
StreamReader.ReadToEnd
jest 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 ReadAllText
po prostu dzwonisz StreamReader.ReadToEnd
wewnętrznie.
Porównanie testów porównawczych File.ReadAllLines
vs StreamReader ReadLine
z obsługą plików C #
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.
Jak File.ReadAllText
inni 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();
}
Przeglądanie kodu wskazującego przez ILSpy Znalazłem następujące informacje File.ReadAllLines
, File.ReadAllText
.
File.ReadAllText
- Wykorzystuje StreamReader.ReadToEnd
wewnętrznieFile.ReadAllLines
- Używa również StreamReader.ReadLine
wewnę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;
}
File.ReadAllText
?
File.ReadAllText()
jest to po prostu opakowanie StreamReader.ReadToEnd()
. Zgaduję, że dodatkowa warstwa powinna działać nieco wolniej niż StreamReader.ReadToEnd()
.
ReadAllText
jest to tylko opakowanie streamReader.ReadToEnd();
?
string contents = System.IO.File.ReadAllText(path)
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
System.IO.StreamReader myFile =
new System.IO.StreamReader("c:\\test.txt");
string myString = myFile.ReadToEnd();
@Cris przepraszam. To jest cytat MSDN Microsoft
Metodologia
W tym eksperymencie porównane zostaną dwie klasy. Klasa StreamReader
i FileStream
zostanie 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
FileStream
jest oczywiście szybszy w tym teście. StreamReader
Przeczytanie małego pliku zajmuje dodatkowe 50% więcej czasu . W przypadku dużego pliku zajęło to dodatkowe 27% czasu.
StreamReader
szczególnie szuka podziałów linii, podczas gdy FileStream
nie. 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/LF
rozdzielane. Spowoduje StreamReader
to 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ą FileStream
odczytywane 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.
StreamReader.ReadToEnd
?
cóż, najszybszym sposobem oznaczania przy możliwie najmniejszym kodzie C # jest prawdopodobnie ten:
string readText = System.IO.File.ReadAllText(path);
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);
}
}
string content = System.IO.File.ReadAllText( @"C:\file.txt" );
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.
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.
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();
}
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);
}
}
}
}
}
}
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.