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

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

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

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

Ответ
 
Опции темы Поиск в этой теме
Старый 22.02.2011, 17:46   #1
tim91
Пользователь
 
Регистрация: 18.09.2008
Сообщений: 10
По умолчанию копирование строки из файла используя потоки

Суть задачи сводится к построчному анализу файла. Не могу понять как считывать из файла строку использую поток (файл текстовый). Гуглил, решения не нашел. Объясните, пожалуйста, на простом примере.
tim91 вне форума Ответить с цитированием
Старый 22.02.2011, 17:51   #2
ArtGrek
DelphiProger
Участник клуба
 
Аватар для ArtGrek
 
Регистрация: 14.11.2010
Сообщений: 1,023
По умолчанию

Файловые потоки

Теперь разберем возможности работы потомка TStream - TFileStream - файловый поток. Этот класс был специально введен для работы с файлами. Для работы с файловым потоком Вам надо записать в Uses модули classes, Sysutils (classes - включает в себя собственно определение класса, Sysutils - некоторые константы необходимые для работы).

Вот пример записи/перезаписи файла:
Код:
Procedure WriteFileUsingStream(s, FileName:string);
begin	
with TFileStream.create(FileName, fmCreate or fmOpenWrite) do 
	try 
	write(pointer(s)^,length(s)); 
	finally 
	free; 
	end; 
end;
Теперь небольшой разбор:

TFileStream.create - конструктор класса, его вызов требует указания имени файла и опций его открытия, следующие опции определены:

fmCreate = $FFFF;
fmOpenRead = $0000;
fmOpenWrite = $0001;
fmOpenReadWrite = $0002;
fmShareCompat = $0000;
fmShareExclusive = $0010;
fmShareDenyWrite = $0020;
fmShareDenyRead = $0030;
fmShareDenyNone = $0040;

Теперь метод Write - этим методом в файл пишется любая информация из буфера любого типа, Вам надо указать только буффер и количество записываемых байтов. В данном случае используется переменная типа String в качестве буффера, но так как для длинных строк она представляет собой лишь указатель, то конструкция "pointer(s)^" заставляет обращаться именно к ее содержимому.

А вот этот код демонстрирует чтение файла с использованием файлового потока:
Код:
var p:PChar;
begin	GetMem(p, 255); 
	with TFileStream.create('c:\myText.txt', fmOpenReadWrite) do 
	try 
	Seek(10,soFromBeginning); 
	read(p^, 254); 
	finally 
	free; 
	end; 
	showmessage(p); 
	FreeMem(p); 
end;
И пояснения к коду:
1) Никаких проверок длину файла и его наличие здесь не делается - это демонстрационный код, а не готовая процедура чтения.
2) Файл мы считываем в буффер типа PChar (с тем же успехом можно использовать массив или любой другой контейнер). Для тех кто не помнит - процедуры GetMem(p, 255) и FreeMem(p) - распределение памяти для строки и освобождение памяти.
3) Метод потока Seek позволяет установить текущую позицию считывания/записи файла. Первый параметер - номер байта, второй - это от чего считать этот байт (у нас считать от начала файла), возможны варианты:
soFromBeginning - от начала файла
soFromCurrent - от текущей позиции считывания
soFromEnd - от конца файла (в этом случае номер байта должен быть отрицательным или равным нулю)
4) Собственно считывание из потока осуществляется методом read, в котором указывается в качестве параметров буфер в который мы читаем и желаемое количество байт для чтения. Метод read является функцией, которая возвращает количество байт реально прочитанных из потока.

Заканчивая о файловых потоках хочу упомянуть о методе
CopyFrom который позволяет перекачивать информацию из одного потока в другой и о свойствах:

Size - размер файла
Position - текущая позиция чтения/записи потока

Работа с файловыми потоками весьма быстра, этот класс, являсь классом VCL, в то же время базируется на низкоуровневых функциях Windows, что обеспечивает очень высокую скорость работы и стабильность операций. К тому же многие компоненты и классы VCL поддерживаю прямое чтение и запись с файловыми потоками, что занчительно упрощает работу - например TStringList, TBlobField, TMemoField и другие.
Файловые потоки могут быть рекомендованы к использованию в большинстве случаев для чтения и записи файлов (за исключением специфических ситуаций, требующих каких-то других подходов), другими словами если вам надо просто записать или считать файл, используйте файловые потоки.
VirusN13
ArtGrek вне форума Ответить с цитированием
Старый 22.02.2011, 17:58   #3
tim91
Пользователь
 
Регистрация: 18.09.2008
Сообщений: 10
По умолчанию

Код:
sourceFS:=TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
sourceFS.Read(curStr[1], 254);
ShowMessage(curStr);
результат работы - пустая строка(файл не пустой).
tim91 вне форума Ответить с цитированием
Старый 22.02.2011, 18:15   #4
ArtGrek
DelphiProger
Участник клуба
 
Аватар для ArtGrek
 
Регистрация: 14.11.2010
Сообщений: 1,023
По умолчанию

GetMem(curStr, 255);

весь код относителино етои процедуры надо скидывать
VirusN13
ArtGrek вне форума Ответить с цитированием
Старый 22.02.2011, 18:42   #5
tim91
Пользователь
 
Регистрация: 18.09.2008
Сообщений: 10
По умолчанию

Спасибо, уже лучше.
Код:
sourceFS:=TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
GetMem(pointer(curStr), 254);
sourceFS.Read(pointer(curStr)^, SizeOf(curStr));
копирует только часть строки. Если вместо SizeOf(curStr) написать 255, то скопирует больше одной строки. Как копировать строки?

Последний раз редактировалось tim91; 22.02.2011 в 18:45.
tim91 вне форума Ответить с цитированием
Старый 22.02.2011, 18:47   #6
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

SizeOf(curStr) равно 4. поинтер, как-никак.
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 22.02.2011, 18:47   #7
ArtGrek
DelphiProger
Участник клуба
 
Аватар для ArtGrek
 
Регистрация: 14.11.2010
Сообщений: 1,023
По умолчанию

Код:
GetMem(pointer(curStr), 254); //сперва надо выделить памяти а потом создавать, и в конце работы обязательно FreeMem(p); 
sourceFS:=TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
sourceFS.Read(pointer(curStr)^, SizeOf(curStr));
Цитата:
написать 255, то скопирует все
что все сли ты сново вопрос задаеш?
Цитата:
Как копировать строки?
VirusN13
ArtGrek вне форума Ответить с цитированием
Старый 22.02.2011, 18:50   #8
tim91
Пользователь
 
Регистрация: 18.09.2008
Сообщений: 10
По умолчанию

Цитата:
Сообщение от veniside Посмотреть сообщение
SizeOf(curStr) равно 4. поинтер, как-никак.
понятно, а что нужно там написать чтобы скопировать именно строку?
tim91 вне форума Ответить с цитированием
Старый 22.02.2011, 18:50   #9
tim91
Пользователь
 
Регистрация: 18.09.2008
Сообщений: 10
По умолчанию

Цитата:
что все сли ты сново вопрос задаеш?
мне нужно копировать построчно
tim91 вне форума Ответить с цитированием
Старый 22.02.2011, 18:56   #10
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

> а что нужно там написать чтобы скопировать именно строку?

ничего, никто ведь не знает, будет строка длиной 4 или 4000 символов.
Можно просто весь файл загрузить в память (если он не большой, меньше гига), и там искать символы #13, #10.

Или взять TStringList.LoadFromFile(), он сам всё найдёт )
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Открытие файла, используя полный путь к нему kleinsnake Общие вопросы C/C++ 2 09.02.2011 20:12
Создание пустой строки и копирование в неё содержимое предыдущей строки Gvaridos Microsoft Office Excel 2 29.10.2010 13:33
Копирование значения строки из одного Excel-файла в другой Janik Microsoft Office Excel 5 20.09.2010 00:29
потоки сохранение и считывания файла [C++] ArniLand Общие вопросы C/C++ 1 27.05.2010 23:27
Потоки и символ конца строки Deatz Общие вопросы C/C++ 3 07.05.2008 20:02