Чтение файлов как лучше поступить?
private void button3_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK) ;
FileStream f = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(f, Encoding.Default );
int buf = 0;
long pb = f.Length / 100;
for (int i = 0; i < f.Length; i++ )
{
if (i % pb == 0) progressBar1.Increment(1);
buf = br.Read();
richTextBox2.AppendText(Convert.ToString(buf));
richTextBox1.AppendText(Convert.ToString(Convert.ToChar(buf)));
}
}
Впринципе если можно подскажите способ как можно побитно быстро считать файл ... то есть файл представить в двоичном формате... зранеее большое спасибо ...
Побитно считать нельзя! Ничем и ни откуда! Можно считать побайтно, а потом обрабатывать бинарными операторами! (Но это в С/С++)!
Про С# не могу утверждать (ведь код, как я заметил - C#)!
Советую почитать справочник по фреймворку - все станет на свои места!
Должен быть метод, типа:
const char *data() const;
Вот он Вам и нужен!!!
ИМХО,нигде не заметно,что это C#
Чтобы ускорить чтение,читайте файл не побайтно(ыбли тут умельцы,тоже что-то хотели побитно считать),а в небольшой буфер–тогда скорость заметно возрастёт.Ну а если файл маленький,то его можно целиком считать
В заголовке функции:
private void button3_Click()
Проблема ваша во первых в том, что вы читаете побайтно в то врямя, как минимальный объем, который можно прочесть с диска, составляет 512 байт (определяется размером кластера файловой системы).
Помимо этого, в вашем цикле происходит приращение прогрессбара, разнообразные приведения типов - что в сумме и дает тормоза.
может быть кто нибудь еще подскажет как ускорить?
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
FileStream f = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read);
BufferedStream bs = new BufferedStream(f,4096);
byte[] b = new byte[4096];
string s = "";
int buf = 0;
while ((buf = bs.Read(b, 0, 4096)) > 0)
for (int i = 0; i < 4096; i++)
s += b;
textBox3.Text = s;
f.Close();
bs.Flush();
bs.Close();
}
}
P.S. Код действительно на C#.
может быть кто нибудь еще подскажет как ускорить?
Дело не в чтении файла. Медленно работает TextBox.
Попробуйте открыть большой файл (хотя бы 1 Мб) Блокнотом - тоже очень долго.
И еще один вопрос в догонку: можно ли написать функцию для чтения структуры из файла на C++, после загнать в библиотеку и использовать ее в C#, как промежуточное звено?
Во вторых, в вашем примере как минимум нерационально выполняется операция добавления текста в строку. Да и сам текстбокс как уже сказали - не самый быстрый компонент.
Кроме того - размер кластера - это минимальный объем, который может читать ОС - но это не значит что вы должны читать минимальными объемами.
EqKeeper да, можно.
Не очень понятно - это к чему? почему и где нет указателей?
может быть кто нибудь еще подскажет как ускорить?
1) BufferedStream и так содержит внутренний буфер. Нет никакого смысла читать из него в собственный byte[] массив. Создайте поверх этого потока банальный StreamReader и вытаскивайте строки из него.
2) Научитесь использовать using конструкцию для работы с потоками:
using(StreamReader reader = new StreamReader(stream)) {
// работаем с reader
}
3) Вам уже сказали, файлы большого размера построчно загружать в TextBox нерационально. Нужно создавать дополнительный поток и читать в нем, периодически догружая данные в компоненту; альтернативным способом может быть ленивая догрузка данных в компонент по мере прокрутки файла пользователем. Например, Microsoft Word комбинирует эти два подхода.
Обсуждается чтение файла. Дабы не плодить одинаковых тем (ибо обязательно сошлют в эту, которая рядом), свой вопрос задал здесь, тем более что суть та же: как лучше считать файл.
В C# нет указателей. Вернее они есть, но вызываются через пятую точку внутри специального блока и использовтаь их не рекомендуется.
Чтобы было понятнее - приведу пример. Есть файл. Его формат документирован. Файл большой, внутри него можно многое найти. Первым идет заголовок длиной, скажем, 256 байт. Его нужно считать и разложить по полочкам для дальнейшего использования. В BCB я это делал так:
typedef struct
{
int a;
int b;
int c;
char d[12];
char e[32];
char f:1; // Это...
char g:2; // ...биты
} FileHeader;
FILE *f; // файл
FileHeader head; //структура
//Открываем файл на двоичное чтение
f = fopen( "d:\some_file.dat", "rb");
//Читаем первые 57 байт файла f в структуру head
fread(&head, sizeof(FileHeader), 1, f);
//Закрываем файл
fclose(f);
Очень удобно и быстро. Если следовать примерам из этой темы - код разрастется до сумасшедших величин - каждый элемент структуры придется запонлять отдельно.
Вот я и спрашиваю - можно ли портировать этот код на C#. В идеале - такую же компактную и удобную замену. Если это невозможно - расширение для C# в виде чего угодно.
Может кто-нибудь что-нибудь посоветовать? Слышал что-то о структурах и с... с... с... сериализации. Но ничего не понял. =\
2 По поводу Bufferstream не совсем понял в МСДН написано что метод Read использует 3 параметра массив байт (куда читать) смещение откуда читать и кол-во байт тобишь по сколько читать ... возращаемое значение int показывает сколько байт считать удалось ... Какой такой встроеный буфер?? Вся так сказать медлительность происходит из за преобразования байт в строку и + текст бокс именно эту проблему я не знаю как решить то есть как можно считанную информацию побыстрее вывести ....
По поводу структуры ... а нафига она нужна когда есть классы ? Создай касс с такими же параметрами и пользуйся наздоровье ...
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
richTextBox1.Clear();
FileStream f = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read);
BufferedStream bs = new BufferedStream(f);
StringBuilder sb = new StringBuilder();
byte[] b = new byte[4096];
int buf = 0;
while ((buf = bs.Read(b, 0, 4096)) > 0)
for (int i = 0; i < buf; i++)
sb.Append(b);
richTextBox1.AppendText(sb.ToString());
label3.Text = sb.Length.ToString();
f.Close();
bs.Flush();
bs.Close();
}
}
RichTextBox намного быстрее TextBox ...
Может есть компонент еще быстрее ??
E.g. 32768 bytes
Ну а ежели хотите ещё быстрей–пользуйте WinAPI.Это ж .NET,как-никак…
Проблема не в создании структуры, а в ее наполнении.
E.g. 32768 bytes
Ну а ежели хотите ещё быстрей–пользуйте WinAPI.Это ж .NET,как-никак…
Да спасибо увеличение буфера помого снизить время открытие 15 м файла до 11 секунд ...посморел исходники Alkepad он написан на С++ и сделан на WinApi ... просто думаю вот что ... при открытии большого файла из stringbuilder в string компилятор непереводит ... говорит мол слишком большое знчение .... чем бы восользоваться? попробую массивом строк ...
По поводу классов ну можно создать класс с какими нужно значениями сделать метод считки использоуя Binaryreader он может считываь значения стандартных размеров ...правда вот как строу считать не соовсем понятно онаж может быть хрен знае какого размера .... но всеравно посмотри МСДН про binaryreader
С массивом строк я в пролете буду искать еще что нить ...
....
В BCB я это делал так:
typedef struct
{
int a;
int b;
int c;
char d[12];
char e[32];
char f:1; // Это...
char g:2; // ...биты
} FileHeader;
....
Вот я и спрашиваю - можно ли портировать этот код на C#. В идеале - такую же компактную и удобную замену.
Портировать можно. И код будет выглядеть также как в C++.
Только чего-то не понятно, что нужно - быстро прочитать файл по-байтно или прочитать из файла структуру в unmanaged-стиле?
По первому пункту вам уже ответили - НЕ заполняйте текстовое поле В ЦИКЛЕ чтения файла. Заполняйте его в отдельном потоке.
По поводу второго вопроса, лучше создать отдельную тему с четким описанием структуры на C/C++ и внятным описанием желаемого эффекта.
Если можно расскажите поподробнее как реализовать пожалуйсто ...
Вы читать что вам пишут пробовали?
НЕ заполняйте текстовое поле В ЦИКЛЕ чтения файла. Заполняйте его в отдельном потоке.
Может и так..но это не главное! Вьюэры, способные открывать большие файлы (TotalCommander'овский lister, например) используют динамическую подгрузку!
Если исхитриться и удалить файл, в тот момент, когда он открыт вьюэром(вьюэром с динамической подгрузкой), то при скроллинге в этом вьюэре, содержимое исчезнет ( своими глазами видел )!
Я же говорю, своими глазами видел! Файл был заблокирован другим приложением, а потом открыт для чтения вьюэром! Приложение захлопнулось и файл удалило (вероятно силовой метод). Но больше походе на глюк, т.к. в теории, открытый файл удалить нельзя! Зато есть "силовой метод", - так работают unlocker'ы!
Но не суть важно. Главное уже сказано - динамическая подгрузка...
Можно, если он открыт с разрешениями на любую деятельность (поднят флаг FileShare.Delete).
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
const int Col = 262144;
richTextBox1.Clear();
FileStream f = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read);
BufferedStream bs = new BufferedStream(f,Col);
StringBuilder sb = new StringBuilder();
byte[] b = new byte[Col];
int count;
if (f.Length < Col) count = 1;
else count = Convert.ToInt32(f.Length / Col +1);
string[] sm = new string[count];
int buf = 0;
int k = 0;
while ((buf = bs.Read(b, 0, Col)) > 0)
{
for (int i = 0; i < buf; i++)
sb.Append(b);
sm[k] = sb.ToString();
k++;
sb.Remove(0, sb.Length);
}
richTextBox1.Lines = sm;
label3.Text = f.Length.ToString() + " "+Convert.ToString(k);
f.Close();
bs.Flush();
bs.Close();
}
}
Думаю над тем как бы сделать процес генерации этих строк и паралельно ему вывод в textBox что бы процес генерации не простаивал ожидая пока в текстБокс будет записана определенная строка а тут же генерировал новую... наверно их надо скидывать в какой нибудь буфер а другой поток бы их оттуда забирал....
Какие есть идеи ?
ой не заметил что тут несколько страниц.. извените.. уже нашел ответы =)
Я думаю это можно сделать так. Берёшь RichEdit, убираешь у него скроллбары (вообще), сажаешь его на форму, к нему цепляешь скролл бар (отдельный компонент). С этим скроллбаром ты можешь делать всё, что угодно, в том числе задать ему реальный размер текста.
Ну, а RichEdit в этом случае просто как подвижное окно для отображения используется - либо ты грузишь в него текст блоками и прокручиваешь RichEdit, либо (что мне кажется лучше и по производительности, и по простоте реализации) заносишь в него небольшой кусок текста, начинающийся со строки, на позиции которй стоит сейчас скроллбар.
Да, спасибо. Правда я так думал уже. И даже попытался сделать, но попутно возникло несколько проблем. Одна из них где взять нормальный скроллбар. Поглядел какой-то Microsoft Forms 2.0 Scrollbar он даже на колесо мыши не реагирует. А так все это мне, собственно говоря, только ради интереса.
Ну, я в .Net не знаток, а так, в WinAPI можно было бы очень просто ловить событие колёсика на RichEdit'е. По идее, что-то такое должно быть и в .Net.
p.s: скорллбару-то на колесо реагировать и не обязательно, ему-то оно зачем :)