Jestem pewien, że wszyscy znamy i prawdopodobnie używamy mnóstwa kodu dostarczonego w książkach, Internecie, itp. Do czytania pliku przy użyciu C#. Coś tak prostego jak ...Zaawansowane czytanie pliku
StringBuilder fiContents = new StringBuilder();
using (StreamReader fi = new StreamReader(@"C:\a_file.txt"))
{
while (!fi.EndOfStream)
{
fiContents.Append(fi.ReadLine);
}
}
A może coś tak krótkie jak ...
using (StreamReader fi = new StreamReader(@"C:\a_file.txt"))
fiContents.Append(fi.ReadToEnd());
Teraz chodźmy Super Saiyan na chwilę i zrobić naprawdę wymyślnych rzeczy jak mają BackgroundWorker
który pozwoli pokazujemy obraz ładujący (to, czego użyję), dostarczę licznik czasu procesu lub ProgressBar
.
public void ReadFile(string filename)
{
BackgroundWorker procFile = new BackgroundWorker();
// Progress 1: If we want to show the progress we need to enable the following property
// procFile.WorkerReportsProgress = true;
profile.DoWork += new DoWorkEventHandler((object obj, DoWorkEventArgs ev) =>
{
StringBuilder fiContents = new StringBuilder();
using (StreamReader fi = new StreamReader(filename))
{
while (!fi.EndOfStream)
{
// Progress 2: Report the progress, this will be dealt with by the respective handler (below).
// procFile.ReportProgress((int)(fi.BaseStream.Length/fi.BaseStream.Position)/100);
fiContents.Append(fi.ReadLine);
}
}
ev.Result = fiContents;
}
/* Progress 3: The handler below will take care of updating the progress of the file as it's processed.
procFile.ProgressChanged += new ProgressChangedEventHandler((object obj, ProgressChangedEventArgs ev) =>
{
// Progress 4: Do something with the value, such as update a ProgressBar.
// ....
}
*/
procFile.RunWorkerCompleted += new RunWorkerCompletedEventHandler((object obj, RunWorkerCompletedEventArgs ev) =>
{
// Do something with the result (ev.Result), bearing in mind, it is a StringBuilder and the ev.Result is an object.
StringBuilder result = ev.Result as StringBuilder;
// ....
}
}
+++++ +++++ +++++ +++++
Czas rzeczywisty pytanie ... Powyższy była rozgrzewka i pokazać obecny poziom zrozumienia, więc nie mam do czynienia z nimi jako potencjalnymi odpowiedziami.
Jestem prawie robi ostatni przykład kodu podany powyżej (tj. Przy użyciu BackgroundWorker
) i wyrzucając zawartość tego, co czyta się do RichTextBox
. Proste rzeczy naprawdę.
Problem, z jakim mam do czynienia, to przetwarzanie dużych plików (np. ~ 222 MB). Przypadek polegający na zrobieniu pliku .txt, przeczytaniu go, wypchnięciu jego wyniku za pomocą StringBuilder
do RichTextBox
. Nie można załadować pliku, otrzymuję numer OutOfMemoryException
. Jednym ze sposobów obejścia tego, co zajmuje znaczną ilość (i wciąż nie jest ładowany plik), jest iterowanie ciągu znaków i dodawanie każdego znaku (jako char
) z pliku StringBuilder
.
Zawsze używałem najbardziej podstawowych i najprostszych sposobów czytania plików (takich jak powyższe przykłady), ale czy ktoś ma jakieś wskazówki, jak poprawić to? Sposoby przetwarzania bardzo dużych plików? itp.
Nawet jako element dyskusji, chętnie przyjmuję Twoje pomysły.
+++++ +++++ +++++ +++++
Edycja 1 (@TaW) wyjątek został wyrzucony gdy próbuje umieścić string
do RichTextBox
...
FileProcessing.RunWorkerCompleted += new RunWorkerCompletedEventArgs((object obj, RunWorkerCompletedEventArgs e) =>
{
// 'Code' is the RichTextBox in question...
Code.Text = "";
if (e.Result is StringBuilder)
{
Code.Text = (e.Result as StringBuilder).ToString();
}
}
Osobiście używam tylko 'File.ReadAllText (filename)' ale jestem leniwy. – Will
Krótka odpowiedź brzmi, że aby załadować plik, który jest zbyt duży dla pamięci, po prostu nie można załadować go wszystkie naraz. Obciążanie tylko części pliku, która obecnie jest widoczna w przewijanym sterowaniu, jest powszechnym rozwiązaniem. –
Odczytanie pliku o wielkości 200 MB powinno zająć tak mało czasu, że pasek postępu i pracownik w tle będą przesadne. –