Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Microsoft Office и VBA программирование > Microsoft Office Excel
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 27.05.2013, 21:19   #1
strannick
Форумчанин
 
Регистрация: 21.10.2011
Сообщений: 433
По умолчанию Импорт Большого текстового файла (14 млн. строк) с разбиением

Добрый день, уважаемые форумчане!
Имеется Большой файл .txt (около 14 млн. строк). 1 строка - 1 слово. Пытаюсь разбить его по 1 млн. строк. У EducatedFool на сайте есть макрос разбиения текстового файла на файлы с заданным количеством строк. Но на моем выдает ошибку 7 "Мало памяти". Вручную как-то не очень хочется его делить. Подскажите варианты. Поиск вразумительных вариантов не дал.
Заранее спасибо!

P.S. Щас придет Hugo, загонит все и всех в массивы, поделит и выгрузит
strannick вне форума Ответить с цитированием
Старый 27.05.2013, 21:24   #2
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,166
По умолчанию

Не, 14000000 в массив думаю не стОит (и впрямь памяти может не хватить), читайте построчно в массив (1 to 1000000, 1 to 1), затем массив на лист и снова по кругу, пока файл закончится. Будет может медленнее, но зато будет.
Или сразу на лист - но это ооочень долго...
webmoney: E265281470651 Z422237915069 R418926282008

Последний раз редактировалось Hugo121; 27.05.2013 в 21:41.
Hugo121 на форуме Ответить с цитированием
Старый 27.05.2013, 21:48   #3
Скрипт
Форумчанин
 
Регистрация: 24.12.2012
Сообщений: 776
По умолчанию

У меня мало оперативной памяти на компьютере (2 Гб), но этот код выполнился:
Код:
Sub Procedure_1()
    
    Dim myArray(1 To 14000000) As Variant
    Dim i As Long
    
    For i = 1 To UBound(myArray) Step 1
    
        myArray(i) = "text" & i
        
    Next i

End Sub
В "Диспетчере задач" посмотрел:
до запуска этого кода было 735 МБ оперативной памяти;
максимальное количество было задействовано оперативной памяти во время работы кода: 1,4 ГБ.

Получается, что для такого массива понадобилось:
1400 МБ - 735 МБ = 665 МБ

Последний раз редактировалось Скрипт; 27.05.2013 в 21:55.
Скрипт вне форума Ответить с цитированием
Старый 27.05.2013, 22:14   #4
IgorGO
Новичок
СтарожилДжуниор
 
Аватар для IgorGO
 
Регистрация: 05.02.2008
Сообщений: 9,487
По умолчанию

Цитата:
P.S. Щас придет Hugo, загонит все и всех в массивы, поделит и выгрузит
Hugo121, доигрался?
тобою уже пользователей пугают...

strannick, очень правильный ход - если задача не очень интересная, а ответ получить надо (обратите внимание, кто ответил первым)))), правда есть одна ошибка... Hugo121, он еще и в словарь может, причем ему удавалась загнать в словари такие слова..., котырые до этого ни в одном словаре не встречались (Даль и Ожегов - отдыхают)
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете
IgorGO вне форума Ответить с цитированием
Старый 27.05.2013, 22:16   #5
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,166
По умолчанию

У меня тоже отработало.
Я говорил немного о другом - если сразу весь текст прочитать в переменную, затем бить в массив - то это нужно 2*14м строк (т.е. держать весь файл 2 раза в памяти). Затем переменную можно убить, и частями перекладывать из большого массива в миллионные - т.е. 14м+1м.
Если же объявлять по миллиону, заполнять из файла, выгружать и снова - то максимум миллион и одна текущая строка (ну или что там из файла будет в памяти) - что намного меньше.
Ну и сам заполняемый файл Экселя тоже где-то как-то должен жить.
webmoney: E265281470651 Z422237915069 R418926282008
Hugo121 на форуме Ответить с цитированием
Старый 27.05.2013, 23:36   #6
strannick
Форумчанин
 
Регистрация: 21.10.2011
Сообщений: 433
По умолчанию

Цитата:
Сообщение от Скрипт Посмотреть сообщение
У меня мало оперативной памяти на компьютере (2 Гб), но этот код выполнился
у меня подвисло(((

IgorGO насчет словарей - это я забыл))) было дело и неоднократно. Кстати, мой исходный файл - это словарь (английские слова и буквосочетания). Вот такой каламбурчик.

Hugo121 Видел на планете по такой почти теме вариант через массив, но не въехал. А вот "построчно" упоминание тоже встречалось, но примера так и не нашел. В загашниках не найдется?
strannick вне форума Ответить с цитированием
Старый 28.05.2013, 00:34   #7
doober
Старожил
 
Аватар для doober
 
Регистрация: 02.05.2009
Сообщений: 3,907
По умолчанию

Цитата:
В загашниках не найдется?
В загашнике есть Скальпель,самописный
Текстовый файл чуть больше 16 млн.строк.
Строка длинной 60 символов.
Файл 998 метров.
Скальпель режет на файлы по 1 млн. строк со скоростью 1 файл -3 секунды.
Памяти берет 30 метров.
Анализ,обработка данных Недорого

Последний раз редактировалось doober; 28.05.2013 в 00:36.
doober вне форума Ответить с цитированием
Старый 28.05.2013, 00:37   #8
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,166
По умолчанию

По задаче словарь не нужен - с ним возни больше. Набрать в словарь легко, выгрузить сложнее.
Вот нашёл пример чтения построчно - там правда ещё и словарь, и разбивка строк в массив - на это не смотрите

Код:
Const ForReading = 1

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile _
    ("c:\temp\Test.txt", ForReading)

	With CreateObject("Scripting.Dictionary")
.CompareMode = 1

Do Until objTextFile.AtEndOfStream
    strNextLine = objTextFile.Readline
    arr = Split(strNextLine)
    For i = 0 to Ubound(arr)
        .item(arr(i))=0&
    Next
Loop

msgbox .count
end with
webmoney: E265281470651 Z422237915069 R418926282008
Hugo121 на форуме Ответить с цитированием
Старый 28.05.2013, 07:22   #9
Скрипт
Форумчанин
 
Регистрация: 24.12.2012
Сообщений: 776
По умолчанию

Цитата:
Hugo121: Вот нашёл пример чтения построчно
я что-то не понял сложность задачи. Почему вы что-то искали, а не просто написали код по взятию данных из текстового файла в VBA-массив? В чём сложность?


strannick, в двух процедурах в константах нужно указать пути и имена текстовых файлов.

Код:
Sub Main()
    
    
    '1. Помещаем в константу "mySource" путь и имя текстового файла,
        'из которого нужно взять данные.
    Const mySource As String = "C:\Users\User\Desktop\Новый текстовый документ.txt"
    
    '2. Помещаем в константу число, которое
        'означает, сколько строк будет в массиве.
    Const mySize As Long = 1000000
    
    
    Dim myArray() As Variant
    Dim myLineIndex As Long
    Dim myFileIndex As Long
    
    
    '3. Подготавливаем массив "myArray" к использованию.
    ReDim myArray(1 To mySize)
    
    
    '4. Открываем текстовый файл.
    '"For Input" переводится "для ввода", а нам нужно открыть
        'для чтения. На самом деле всё правильно, просто
        'это какая-то нестыковка в терминах.
    '1 - это имя в виде числа, которое даётся файлу.
        'С помощью этого имени можно обращаться к файлу.
    Open mySource For Input As 1
    
    
    '5. Двигаемся от строки к строке по текстовому файлу.
        'Явно команды нет для перехода с одной строки на другую.
        'Переход к следующей строке происходит после
        'команды "Line Input".
    'Двигаемся от строки к строке, пока не достигнем конца файла.
    Do While EOF(1) = False
        
        'Сразу создать массив с нужным количеством
            'строк мы не всегда сможем, т.к. может не хватить
            'оперативной памяти. Поэтому будем периодически
            'очищать массив.
        '6. С помощью переменной "myLineIndex" будем подсчитывать,
            'сколько строк текстового файла мы уже взяли в массив.
        myLineIndex = myLineIndex + 1
        
        'Если в массиве уже нужное количество строк.
        If myLineIndex > mySize Then
        
            '7. Формируем фрагмент имени текстового файла, в который
                'перенесём данные.
            myFileIndex = myFileIndex + 1
            
            '8. Переносим данные из массива куда-нибудь,
                'например в другой текстовый файл.
            Call Procedure_1(myArray(), myLineIndex - 1, myFileIndex)
                
            '9. Очищаем массив.
            ReDim myArray(1 To mySize)
            
            '10. Подготавливаем переменную "myLineIndex".
            myLineIndex = 1
                
        End If
    
        '11. Берём данные из текущей строки текстового файла
            'и помещаем в массив.
        Line Input #1, myArray(myLineIndex)
    
    Loop
    
    '12. Переносим остатки в текстовый файл.
    myFileIndex = myFileIndex + 1
    Call Procedure_1(myArray, myLineIndex, myFileIndex)
    
    
    '13. Закрываем текстовый файл.
    Close 1

End Sub

Sub Procedure_1(myArray() As Variant, myLineIndex As Long, myFileIndex As Long)

    'Перенос данных из массива в текстовый файл.
    
    
    '1. Помещаем в константу имя папки, где будут находиться
        'текстовые файлы и первый фрагмент имени файла.
    Const myFolder As String = "C:\Users\User\Desktop\Новая папка\Файл_"
    

    Dim i As Long
    
    
    '2. Создаём и одновременно открываем текстовый файл.
        'Здесь также перевод слова "Output" (вывод) не совпадает
        'с тем, для чего мы открыли текстовый файл. Мы его
        'открыли для ввода.
    Open myFolder & myFileIndex & ".txt" For Output As 2
    
        '7. Переносим данные из массива в текстовый файл.
        For i = 1 To myLineIndex Step 1
        
            Print #2, myArray(i)
            
        Next i
       
    '8. Закрываем текстовый файл.
    Close 2

End Sub
Примечания
  1. Про работу с текстовыми файлами можно почитать на русском языке в самоучителях. Часто в VBA-самоучителях есть специально глава для работы с текстовыми файлами.
  2. Данный код предназначен для работы с текстовыми файлами с кодировкой "ANSI". Если предполагается работать с текстовыми файлами с кодировкой "Unicode", то нужно внести изменения в код или вообще отказаться от использования "Open" и использовать что-нибудь другое, например, объект "File System Object", или VBA-инструменты для работы с файлами, которые есть в самих программах "MS Office".

Последний раз редактировалось Скрипт; 28.05.2013 в 08:31.
Скрипт вне форума Ответить с цитированием
Старый 28.05.2013, 08:28   #10
DiemonStar
Старожил
 
Регистрация: 08.02.2012
Сообщений: 2,173
По умолчанию

Цитата:
Имеется Большой файл .txt (около 14 млн. строк). 1 строка - 1 слово.
Не так и много памяти. Средняя длина слова составляет около 10-12 символов, т.е. порядка 10 байт. Так что на массив потребуется 140-170 мб оперативки... Так что для обработки и 1Гб теоретически должно хватать... ну а построчное считывание вообще избавляет от лишних проблем)

вот еще вариант:
Код:
Sub ReadFile()
  Dim I, J
  I = 1
  J = 1
  File = "мой файл"
  Open File For Input As 1
  Do While Not EOF(1)
    Line Input #1, MyString
    Sheets("Лист" & J).Cells(I, 1) = MyString
    If I  = 1000000 Then
      I = 1
      J = J + 1
    Else
      I = I + 1
    End If
  Loop
  Close #1
End Sub
Правильно поставленная задача - три четверти решения.

Последний раз редактировалось DiemonStar; 28.05.2013 в 08:49.
DiemonStar вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
импорт данных из большого txt файла Неологист Microsoft Office Excel 14 28.09.2011 18:45
Импорт в эксел очень большого файла txt danika24 Microsoft Office Excel 10 20.07.2011 16:34
Импорт данных из текстового файла chobo Microsoft Office Excel 7 28.10.2010 14:29
Обработка большого текстового файла и составление по нему отчета erosss Помощь студентам 6 05.05.2010 13:18