Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.79/29: Рейтинг темы: голосов - 29, средняя оценка - 4.79
8 / 8 / 1
Регистрация: 19.04.2012
Сообщений: 71

Очень большой string[] buf

01.07.2016, 03:17. Показов 5945. Ответов 11
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Суть. Есть софт, который кушает текстовые данные из лог-файла. Значения отделяются друг от друга меткой. Размер файла варьируется от 2 Мб до 1000 Мб. Файлы от 1Кб до 64Мб обрабатываются без проблем.
Есть код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
            
            StreamReader ds = new StreamReader(newstrFile);  // открыли поток
            string TextFile = ds.ReadToEnd();                           // прочитали весь файл
            ds.Close(); 
 
            int strLength = TextFile.Length;        // длина строки
 
            TextFile = TextFile.Replace("МЕТКА", ".");  // меняем метку на символ
 
            if (TextFile != null)
            {
                string[] buf = TextFile.Split('.'); //разбиваем огромную строку на массив string и вот тут возникает проблема.
             }
Если файл от 64 Мб и выше, то выскакивает исключение, что недостаточно памяти.
Для файлов меньшего размера, всё соответственно, ОК.

И собственно сабж, как обработать очень большую строку?
Понимаю, что нужно реализовывать в цикле и с применением буфера, но как сделать сие для string[] не сообразил.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
01.07.2016, 03:17
Ответы с готовыми решениями:

Какие есть средства в C# для работы с числами с очень большой точностью?
Пишу архиватор, построенный на принципе арифметического кодирования, и требуется очень большая точность, порядка 1000 знаков после запятой....

Поиск дублей в большой строке с разделителями в List<string>
Есть текстовый файл следующей структуры: &quot;SOMETEXT&quot;;&quot;ID_NUMBER&quot;;&quot;SOMETEXT&quot;; Пример: &quot;РСЧ 111222333444555666...

Очень большой Bitmap,прорисовка.
Клепаю прогу которая открывает файл, считывает побитно его и, если 1 - выводит квадратик, 0 - точку. И так по порядку, рядами по 80 байт....

11
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
01.07.2016, 03:26
Если бы вы привели хотя бы небольшой пример файла, было бы гораздо проще предложить какое-то решение. А как вы делаете какие-то непонятные действия, например зачем делать Replace, если можно сразу сделать Split, да и вообще если там гигабайтные файлы, то лучше читать по одной строке. Также вы не написали чего хотите в конечном итоге добиться, зачем вам именно string[]?
0
8 / 8 / 1
Регистрация: 19.04.2012
Сообщений: 71
01.07.2016, 07:57  [ТС]
Ну вот так выглядит сам файл:
Bash
1
96728401MTK1CTR113059170MTK1CTR180894672MTK1CTR0MTK1CTR3768639MTK1CTR0MTK1CTR0MTK1CTR0MTK1CTR5024852MTK1CTR0MTK1CTR0MTK1CTR0MTK1CTR320334315MTK1CTR320334315MTK1CTR0MTK1CTR0MTK1CTR231143192MTK1CTR0MTK1CTR0MTK1CTR0MTK1CTR0MTK1CTR0MTK1CTR0MTK1CTR0MTK1CTR80397632MTK1CTR0
Представьте только, что размер это файла ~130Мб.
Строка в этом файле фактически одна, т.к. контролер пишет все в одну строку, добавляя в конец текстового файла.
MTK1CTR это метка. Остальные цифры это номера приборов, датчиков, которые были опрошены.
Метка может быть не одна,они друг от друга отличаются, это я привел пример.

Суть в том, чтобы взять это текстовый файл, достать из него все данные, убрать из него метку(метки), и то что осталось (номера) затолкать в буфер. Например мы достали из файла цифру 96728401, нам теперь её нужно сохранить в буфер, чтобы потом делать в этом буфере поиск, затолкать это дело в Oracle и всё в таком роде.

Далее с этим буфером работают уже другие подпрограммы и процедуры.

Добавлено через 30 минут
Заменить Split(Char) на Split(String) можно:
C#
1
string[] buf = TextFile.Split(new[] { "МЕТКА" }, StringSplitOptions.None);
Но толку это не даст, т.к. памяти всё равно не хватит.

Добавлено через 1 час 55 минут
Пробовал использовать несколько другой подход:

C#
1
2
3
4
5
6
7
8
9
10
using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs))
{
    string line;
    while ((line = sr.ReadLine()) != null)
    {
 
    }
}
но толку это тоже не дало, при выполнении sr.ReadLine() снова исключение о нехватке памяти.
Неужели нет способа обрабатывать файлы большого размера?
0
 Аватар для EveKS
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
01.07.2016, 08:14
shirase, а если, в зависимости от размера принять в несколько srting, потом их вернуть?

Зачем делать один buf
0
8 / 8 / 1
Регистрация: 19.04.2012
Сообщений: 71
01.07.2016, 09:17  [ТС]
Я думал об этом, но не смог пока написать реализацию.
Попробовал сделать с буфером. Вышло что-то вроде:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 using (Stream stream = System.IO.File.OpenRead(newstrFile))
            {
                using (StreamReader streamReader = new
                StreamReader(stream, System.Text.Encoding.ASCII))
                {
                    string[] buffer = new string[100];
                    string read = "";
                    while (streamReader.Peek() > -1)
                    {
                        string[] buf = read.Split(new[] { "@" }, StringSplitOptions.None);
 
                    }
                }
            }
но видимо ошибся и buf пустой.
если бы это был не string[], а char[], то
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
using (Stream stream = System.IO.File.OpenRead(fileName))
{
       using (StreamReader streamReader = new
        StreamReader(stream,    System.Text.Encoding.ASCII))
         {
            char[] buffer = new char[202];
              int read = 0;
                while (streamReader.Peek() > -1)
                 {
                   read = streamReader.Read(buffer, 0, 202);
                }
                     }
             }
работает, в массив char[] идут символы, но не совсем то, что нужно.
Может кто сможет адаптировать?
0
Кодогенератор
 Аватар для hepper
200 / 200 / 51
Регистрация: 15.06.2011
Сообщений: 794
01.07.2016, 09:52
посмотри этот вариант

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var path = "c:/test.txt";
            var blockLenght = 4096;
            var buff=new byte[blockLenght];
            int offset = 0;
            var list=new List<string>();
            using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                var len = blockLenght;
                while ((len=fs.Read(buff, 0, blockLenght)) >0)
                {
                    var dataStr = Encoding.ASCII.GetString(buff);
                    offset += dataStr.LastIndexOf("MTK1CTR", StringComparison.Ordinal);
                    var dataArr = dataStr.Split(new string[] { "MTK1CTR" },StringSplitOptions.RemoveEmptyEntries);
                    //или
                    //dataStr=dataStr.Replace("MTK1CTR", ".");
                    //dataArr = dataStr.Split('.',StringSplitOptions.RemoveEmptyEntries);
                    list.AddRange(dataArr);
                    list.RemoveAt(list.Count-1);
                    if(len<blockLenght)break;
 
                    fs.Seek(offset, SeekOrigin.Begin);
                    buff=new byte[blockLenght];
                }
            }
0
158 / 187 / 48
Регистрация: 25.11.2013
Сообщений: 978
01.07.2016, 09:57
Memory-Mapped Files
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18285 / 14208 / 5368
Регистрация: 17.03.2014
Сообщений: 28,887
Записей в блоге: 1
01.07.2016, 10:37
shirase, я бы как-то так сделал:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
static IEnumerable<string> ReadParts(string path, string separator)
{
    using (var fstream = File.OpenRead(path))
    using (var reader = new BinaryReader(fstream))
    {
        StringBuilder sb = new StringBuilder(50);
        char[] buffer = new char[32000];
        int idx = 0;
        while (fstream.Position < fstream.Length)
        {
            int charsRead = reader.Read(buffer, 0, buffer.Length);
            for (int i=0; i<charsRead; i++)            
            {
                char ch = buffer[i];
                if (ch == separator[idx])
                {
                    idx++;
                    if (idx == separator.Length)
                    {
                        yield return sb.ToString();
                        sb.Clear();
                        idx = 0;
                    }
                }
                else
                {
                    sb.Append(ch);
                }
            }
        }
        
        if (sb.Length>0) yield return sb.ToString();
    }
}
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
01.07.2016, 14:19
OwenGlendower, StringBuilder не зря ограничен 8000 символами Это я про 32000
0
8 / 8 / 1
Регистрация: 19.04.2012
Сообщений: 71
03.07.2016, 03:52  [ТС]
Цитата Сообщение от OwenGlendower Посмотреть сообщение
shirase, я бы как-то так сделал:
Спасибо, в общих чертах то что нужно.
Вызываю так:
C#
1
2
3
            foreach (string n in ReadParts(newstrFile, "@")) {
 
            }
А вот вопрос, как мне переложить то, что выдает ReadParts в какой-либо буфер за пределами foreach?

Добавлено через 5 минут
Цитата Сообщение от hepper Посмотреть сообщение
посмотри этот вариант
Спасибо! Этот метод тоже работает, но мне несколько непонятно что дает это:

C#
1
2
fs.Seek(offset, SeekOrigin.Begin);
buff = new byte[blockLenght];
А потом я дописал еще буфер для теста:
C#
1
2
int strBuf = dataArr.Length;
int[] arr = new int[strBuf];
И на выходе в буфере arr[] и буфере dataArr[] разный порядок байтов.
И на выходе они отличаются по размером на пару килобайт.
С чем это связано я пока не отследил.

Добавлено через 35 минут
Пробовал сделать так:
C#
1
2
3
4
5
6
7
8
9
    List<string> stringlist = new List<string>();
            string[] mybuf = {};
 
            foreach (string n in ReadParts(newstrFile, "@")) {
 
               stringlist.Add(n);
               mybuf = stringlist.ToArray();
 
            }
Но после цикла foreach mybuf оказывается пустой.
Пробовал mybuf = { n }; но ругается на ошибку приведения типов string в string[]

Добавлено через 17 часов 30 минут
Цитата Сообщение от OwenGlendower Посмотреть сообщение
shirase, я бы как-то так сделал:
Дописал как достать значения из цикла foreach:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
List<string> stringlist = new List<string>();
            string[] mybuf = {};
            byte[] mybytes1 = { };
            int j = 0;
            foreach (string n in ReadParts(newstrFile, "@")) {
 
               stringlist.Add(n);
               mybuf = stringlist.ToArray();
 
            }
            
            mybuf = stringlist.ToArray();
            int strBuf = mybuf.Length;
            int[] arr = new int[strBuf];
 
            for (int i = 0; i < strBuf; i++)
            {
                arr[i] = Convert.ToInt32(mybuf[i]);
             }
маленькие файлы обрабатывает, а вот на файле в 13Мб - я даже не знаю, программа выполняется, но до mybuf = stringlist.ToArray(); не доходит. Ошибок не пишет... Выглядит как будто ушла в вечный цикл.
Буфер arr[] сделал ради проверки, чтобы увидеть, не нарушается ли порядок байтов или еще чего.

Добавлено через 11 минут
Цитата Сообщение от hepper Посмотреть сообщение
посмотри этот вариант
Есть небольшая проблема в алгоритме. думаю связана с blockLenght=4096
При загрузке строки обрезает часть:
Bash
1
2
3
4
5
6
7
8
        [443]   "138183430" string
        [444]   "16330769"  string
        [445]   "12562130"  string
        [446]   "60298224"  string
        [447]   "60298224"  string
        [448]   "60298224"  string
        [449]   "60298224"  string
        [450]   "602"   string        <-- вот тут должно было быть 60298224
0
Кодогенератор
 Аватар для hepper
200 / 200 / 51
Регистрация: 15.06.2011
Сообщений: 794
03.07.2016, 06:03
Цитата Сообщение от shirase Посмотреть сообщение
Есть небольшая проблема в алгоритме. думаю связана с blockLenght=4096
При загрузке строки обрезает часть:
последняя "неполная" часть удаляется - а потом на следующем заходе добавляется
0
8 / 8 / 1
Регистрация: 19.04.2012
Сообщений: 71
03.07.2016, 15:09  [ТС]
Цитата Сообщение от hepper Посмотреть сообщение
последняя "неполная" часть удаляется - а потом на следующем заходе добавляется
Ок, я проверю тогда

Добавлено через 33 минуты
Набросал вот еще вариант:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
            int nCols = 16;
            FileStream fs = new FileStream(newstrFile, FileMode.Open, FileAccess.Read);
            long nBytesRead = fs.Length;
           
            int nLines = (int)(nBytesRead / nCols) + 1;   // вот тут что-то не так
          //  int nLines = (int)(nBytesRead);
            string[] lines = new string[nLines];
            int nBytesToRead = 0;
            byte[] mybytes1;
 
            int strBuf = lines.Length;
            int[] arr = new int[strBuf];
 
 
            for (int i = 0; i < nLines; i++)
            {
                StringBuilder nextLine = new StringBuilder();
                nextLine.Capacity = 4 * nCols;
                
                for (int j = 0; j < nLines; j++)
                {
                    int nextByte = fs.ReadByte();
                    nBytesToRead++;
                    char nextChar = (char)nextByte;  // получаем байт
                    
                    if (nextChar == '@'){ 
                        break;   // исключаем метку, выходим из цикла и заставляем StringBuilder заполнять новую строку
                    }
                        else {
                    nextLine.Append(nextChar);
                  }
 
                }
                // далее просто преобразования для тестирования
                lines[i] = nextLine.ToString();
                arr[i] = Convert.ToInt32(lines[i]);
            }
            fs.Close();
                mybytes1 = arr.Select(x => (byte)x).ToArray();
 
 
                using (FileStream fileStream = new FileStream(newPathFile, FileMode.Append, FileAccess.Write))
                {
 
                    fileStream.Write(mybytes1, 0, mybytes1.Length); 
 
                    fileStream.Flush();
                    fileStream.Close();
                }
Но есть проблема. При использовании
C#
1
            int nLines = (int)(nBytesRead / nCols) + 1;
берется размер всего файла. в теории это посчитали кол-во строк для StringBuilder, но получается так, что от файла весом 1.4Мб получается 860Кб.
Если немного подправить строку:
C#
1
            int nLines = (int)(nBytesRead);
то в какой-то момент на строке arr[i] = Convert.ToInt32(lines[i]); возникает ошибка, что строка имеет неверный формат.
Пока не решил эту проблему.

Добавлено через 1 час 0 минут
Выявил ошибку про неверный формат.
Возникает глубоко в массиве string[]. В строку пишется
Bash
1
16330769￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿
Почему так происходит - не ясно.
Пробовал Trim,Replace, но не помогло.

Добавлено через 1 час 20 минут
Хм, в какой-то момент
C#
1
int nextByte = fs.ReadByte();
считывает байт -1
Что я забыл?

Добавлено через 5 часов 6 минут
-1 оказался конец потока. С остальным разобрался.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
03.07.2016, 15:09
Помогаю со студенческими работами здесь

Что означают buf[0],buf[si],buf[4]
Знающие люди , помогите разобраться ( совсем 0 в ассемблере), что значат все строчки кода с buf,buf,buf ? заполнение строки этими...

Странная ошибка при компиляции очень очень большой проги ,,boomerang,,
Я в общем, даже и не представляю, куда смотреть в поисках ошибки. Ошибка 1 error LNK2019: ссылка на неразрешенный внешний символ...

buf.lenght-buf.length
вообщем наткнулся на такое byte buf = new byte; buf = 1; buf = 2; //ну эта часть кода неважна //меня интересует эта строчка, как...

Очень большой CSV
Всем привет. Решил я наконец запились себе БД и уткнулся в проблему. В чем суть. Есть здоровый CSV (250Мб), который ежедневно...

Очень большой перебор
Всем привет,я новичок,осваиваюсь на C++. В общем,имеется задача. Дано(стандартный ввод) число a(1 &lt;= A &lt;= 255),цель - найти такие...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru