Чтение файла + память

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Чтение файла + память

Сообщение KUKA » 29.01.2013 19:32:23

В общем задача у меня какая считать файл, записать все, что в нем в память и вернуть на это указатель

собственно вот:
Код: Выделить всё
function textfileread(var fn: pchar): pchar;
var fs: file; count: integer; content: pchar;
begin
  count:=0;
   
  if fn <> NIL then
  begin
   Assign(fs,fn);
   if @fs <> NIL then
   begin
     seek(fs, FileSize(fs));
     count:= FilePos(fs);
     reset(fs);
         
     if count>0 then
     begin
       GetMem(content, sizeof(char)*(count+1));
       count:=Blockread(fs, content, count, sizeof(char));
       content[count]:=#10;
     end;
     close(fs);
   end;
  end;
   
  textfileread:=content;
end;


Ошибка следующая:
http://clip2net.com/s/2LK8K
Может кроме этого еще что-то в коде неправильно?
Или есть какие-то уже готовые аналоги?

Списывал с этого кода.
Код: Выделить всё
char *textFileRead(char *fn) {
   FILE *fp;
   char *content = NULL;
   int count=0;
   if (fn != NULL) {
      fp = fopen(fn,"rt");

      if (fp != NULL) {
     
         fseek(fp, 0, SEEK_END);
         count = ftell(fp);
         rewind(fp);

         if (count > 0) {
            content = (char *)malloc(sizeof(char) * (count+1));
            count = fread(content,sizeof(char),count,fp);
            content[count] = '\0';
         }
         fclose(fp);
      }
   }
   return content;
}
KUKA
новенький
 
Сообщения: 46
Зарегистрирован: 22.02.2012 20:54:19

Re: Чтение файла + память

Сообщение bormant » 29.01.2013 20:19:45

Как всё запущено... В первом приближении:
Код: Выделить всё
function textfileread(fn: pchar): pchar;
var
  f: file;
  r, rd: int64;
  content: pchar;
begin
  textfileread := nil;
  if fn <> nil then begin
    content := nil;
    assign(f, fn); reset(f, 1);
    r := filesize(f);
    if r > 0 then begin
      getmem(content, r+1);
      if content <> nil then begin { nil возможен при ReturnNilIfGrowHeapFails = true }
        blockread(f, content^, r, rd);
        if rd = r then
          (content + rd)^ := #0
        else begin
          freemem(content);
          content := nil;
        end;
      end;
    end;
    close(f);
    textfileread := content;
  end;
end;
Если допускается считывание неполного файла (по причине ошибок), то заменить
Код: Выделить всё
        if rd = r then
          (content + r)^ := #0
        else begin
          freemem(content);
          content := nil;
        end;
на
Код: Выделить всё
        (content + rd)^ := #0
Последний раз редактировалось bormant 30.01.2013 09:54:16, всего редактировалось 1 раз.
Аватара пользователя
bormant
постоялец
 
Сообщения: 408
Зарегистрирован: 21.03.2012 11:26:01

Re: Чтение файла + память

Сообщение stikriz » 29.01.2013 21:54:50

А зачем так мучительно пользоваться указателями? Да, и файловыми переменными? Это принципиально?
А то, вот, навскидку можно и так:

Код: Выделить всё
function LoadTextData(const FileName: string): string;
var F: TFileStream;
begin
  F:=TFileStream.Create(FileName, fmOpenRead);
  try
   SetLength(Result, F.Size);
   F.Position:=0;
   F.ReadBuffer(Result[1], F.Size);
  finally
    F.Free;
  end;
end; 


Тока я не отлаживал - прямо тут писал, но принцип понятен, надеюсь.

Добавлено спустя 3 минуты 50 секунд:
Если бы можно было пользоваться TMemoryStream, то его можно загрузить данными, а указатель на данные в F.Memory - если стрим возвращать из функции, а там пользовать его с указателем на данные.
Аватара пользователя
stikriz
энтузиаст
 
Сообщения: 612
Зарегистрирован: 15.03.2006 09:37:47

Re: Чтение файла + память

Сообщение debi12345 » 29.01.2013 22:49:18

У потоков есть метод (кажется) CopyFrom где не-файловый стрим может быть типа TMemoryStream, а у него (если нужно) есть свойство = указатель на данные (в MSEgui это "memory"). Можно смещать позицию копирования относительно "начала" потока - через "position".

Код: Выделить всё
<target_stream>.size:= 0; /* удалить хвост от предыдущих операций */
<source_stream>.position:= 0; /* планируется весь входной поток */
<target_stream>.copyfrom(<source_stream>,<source_stream>.size /* если весь поток целиком * );


<target_stream> ессно должен быть создан заранее.
Например работа сетевыми потоками Synapse строится именно таким образом.
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Re: Чтение файла + память

Сообщение xdsl » 31.01.2013 13:26:24

Вариант от stikriz самый красивый, но если делать точно по заявленному условию задачи и без привлечения сторонних библиотек, то можно так:
Код: Выделить всё
{$mode objfpc}
function getfile(fn:string; var p:pointer):int64;
var f:file;
begin
assignfile(f,fn);
reset(f,1);
result:=filesize(f);
getmem(p,result);
blockread(f,p^,result);
closefile(f);
end;

Недостаток - надо не забывать освобождать память по окончании ее использования.
Ну и проверка самовыводом текста программы. Пусть исходник носит имя 1.pp, тогда проверка будет выглядеть так:
Код: Выделить всё
var p:^char;
    count,i:int64;
begin
count:=getfile('1.pp',p);
for i:=0 to count-1 do write(p[i]);
freemem(p,count);
end.


Если отойти от жестких рамок условия, то есть еще один интересный вариант, вообще без загрузки файла в оперативную память, используя только файлмаппинг. Имя исходник пусть будет 2.pp, целевая ось - linux:
Код: Выделить всё
{$mode objfpc}
Uses BaseUnix;
Var
    fdin : cint;  info: stat;
    i,len  : int64;
    Pin: ^char;
begin
  fdin:=fpOpen('2.pp',O_rdOnly);
  fpfstat(fdin,info);
  len:=info.st_size;
  Pin:=fpmmap(nil,len,PROT_READ,MAP_PRIVATE,fdin,0);

  for i:=0 to len-1 do write(pin[i]);

  fpmunmap(pin,len);
  fpclose(fdin);
end.
xdsl
постоялец
 
Сообщения: 131
Зарегистрирован: 15.01.2009 13:49:03

Re: Чтение файла + память

Сообщение Сквозняк » 31.01.2013 18:59:25

А чем загрузка файла в массив переменной длины не устраивает? Указатель на нулевой элемент массива и будет решением задачи.
Сквозняк
энтузиаст
 
Сообщения: 1129
Зарегистрирован: 29.06.2006 22:08:32

Re: Чтение файла + память

Сообщение KUKA » 01.02.2013 12:13:53

Всем спасибо, решение во втором посте помогло :wink:
KUKA
новенький
 
Сообщения: 46
Зарегистрирован: 22.02.2012 20:54:19


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

Рейтинг@Mail.ru