powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Файлы, отображаемые в память.
25 сообщений из 57, страница 1 из 3
Файлы, отображаемые в память.
    #40017532
Фотография Ежов Дмитрий Сергеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
День добрый.
Есть ли в Дельфи компоненты, позволяющие работать с маппированными файлами.
Желательно, наследники TFileStream

?
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017535
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Работа с такими файлами принципиально не укладывается в интерфейс TStream.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017538
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мой гугл сразу выдал ссылку на https://torry.net/pages.php?id=228
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017550
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov
Работа с такими файлами принципиально не укладывается в интерфейс TStream.
Да ладно, TIBBlobStream укладывается, а MMF нет
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017561
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_TIBBlobStream укладывается, а MMF нет

BLOB - поток данных неизвестного размера, последовательно читаемый кусками. MMF - кусок
данных заданного размера. Ничего общего.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017573
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

Работа с такими файлами принципиально не укладывается в интерфейс TStream.

Серьёзно?..
Я в своё время пытался прикрутить TSteam к MMF ради эксперимента, но за ненадобностью не доделал.
Но ничего "принципиального" я там не вижу.
Код: pascal
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.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
unit smMappedFile;

interface

uses
  System.SysUtils, System.Classes;

type
  TMappedFileStream = class(TStream)
  private
    FFileName: string;
    FHandle: THandle;       // file handle
    FMappedBase: Int64;     // mapping start position
    FMappedSize: NativeInt; // current size of mapping window
    FMapping: THandle;      // handle of file mapping
    FBufferSeek: NativeInt; // file pointer in mapped view
    FDefMapSize: NativeInt; // default size of mapping window
    FMemory: PByte;         // address of mapping window
    FFileSize: Int64;       // available file size
  protected
    function GetSize: Int64; override;
    procedure SetSize(const NewSize: Int64); override;
    procedure RemapAtPosition(RemapBase: Int64);
  public
    constructor Create(const AFileName: string; MapWindowSize: NativeInt = 16777216);
    destructor Destroy; override;
    function Read(var Buffer; Count: Integer): Longint; override;
    function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;
    function Write(const Buffer; Count: Integer): Longint; override;
    property FileName: string read FFileName;
  end;

implementation

uses
  Winapi.Windows, System.RTLConsts;

resourcestring
  sMappedFileIsEmpty = 'Can not map view of zero-length file %s.';
  sSeekBeyondRange   = 'File pointer moved beyond file bounds.';
  sFileMappingError  = 'Error mapping view to file.';
  sStreamIsReadOnly  = 'Stream is read-only.';

function Min(A, B: Cardinal): Cardinal;
begin
  Result := A;
  if B < A then
    Result := B
end;

{ TMappedFileStream }

constructor TMappedFileStream.Create(const AFileName: string; MapWindowSize: NativeInt = 16777216);
begin
  inherited Create;
  FHandle := FileOpen(AFileName, fmOpenRead or fmShareDenyWrite);
  if FHandle = INVALID_HANDLE_VALUE then
    raise EFOpenError.CreateResFmt(@SFOpenErrorEx, [ExpandFileName(AFileName), SysErrorMessage(GetLastError)]);
  FFileName := AFileName;
  PCardinal(@FFileSize)^ := GetFileSize(FHandle, PByte(@FFileSize) + 4);
  if FFileSize = 0 then
    raise EFileStreamError.CreateResFmt(@sMappedFileIsEmpty, [ExpandFileName(AFileName)]);
  FMapping := CreateFileMapping(FHandle, nil, PAGE_READONLY, 0, 0, nil);
  RemapAtPosition(FMappedBase);
end;

destructor TMappedFileStream.Destroy;
begin
  if FMemory <> nil then
    UnmapViewOfFile(FMemory);
  CloseHandle(FMapping);
  FileClose(FHandle);
  inherited;
end;

procedure TMappedFileStream.RemapAtPosition(RemapBase: Int64);
var
  OldBase: Int64;
begin
  OldBase := FMappedBase;
  if FMemory <> nil then
    UnmapViewOfFile(FMemory);
  if FFileSize < FDefMapSize then 
  begin
    FMappedSize := FFileSize;
    FMappedBase := 0;
  end else 
  begin
    FMappedSize := FDefMapSize;
    if FFileSize - RemapBase < FDefMapSize then
      FMappedBase := FFileSize - FDefMapSize
    else 
      FMappedBase := RemapBase;
  end;
  FBufferSeek := FBufferSeek - (OldBase - FMappedBase);
  FMemory := MapViewOfFile(FMapping, PAGE_READONLY, Int64Rec(FMappedBase).Hi, Int64Rec(FMappedBase).Lo, FMappedSize);
  if FMemory = nil then
    raise EStreamError.CreateRes(@sFileMappingError);
end;

function TMappedFileStream.GetSize: Int64;
begin
  Result := FFileSize;
end;

function TMappedFileStream.Read(var Buffer; Count: Integer): Longint;
var
  BytesToRead: Integer;
begin
  Result := 0;
  while (Result < Count) and (FMappedBase + FBufferSeek < FFileSize) do 
  begin
    if FBufferSeek >= FMappedSize then
      RemapAtPosition(FMappedBase + FMappedSize);
    BytesToRead := Min(FMappedSize - FBufferSeek, Count - Result);
    Move((FMemory + FBufferSeek)^, (PByte(Buffer) + Result)^, BytesToRead);
    Inc(Result, BytesToRead);
  end;
end;

function TMappedFileStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
var
  FilePointer: Int64;
begin
  case Origin of
    soCurrent: FilePointer := FMappedBase + FBufferSeek + Offset;
    soEnd: FilePointer := FFileSize + Offset;
  else
    FilePointer := Offset; // soBeginning
  end;
  if (FilePointer < 0) or (FilePointer > FFileSize) then
    raise EStreamError.CreateRes(@sSeekBeyondRange);
  if (FilePointer < FMappedBase) or ((FilePointer - FMappedBase) >= FMappedSize) then 
  begin
    FMappedBase := FilePointer;
    FBufferSeek := 0;
    RemapAtPosition(FMappedBase);
  end else 
    FBufferSeek := FilePointer - FMappedBase;
  Result := FilePointer;
end;

procedure TMappedFileStream.SetSize(const NewSize: Int64);
begin
  raise EStreamError.CreateRes(@sStreamIsReadOnly);
end;

function TMappedFileStream.Write(const Buffer; Count: Integer): Longint;
begin
  raise EStreamError.CreateRes(@sStreamIsReadOnly);
end;

end.

...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017599
Фотография defecator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
alekcvp
Dimitry Sibiryakov

Работа с такими файлами принципиально не укладывается в интерфейс TStream.

Серьёзно?..


сибиряков любит поумничать
в то время, как существует пара десятков реализаций mmf поверх TStream
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017602
Vizit0r
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
моя реализация, проверенная годами работы.
На маке и линухе работает, на андроиде тоже.

Проверок на права доступа к файлу и т.д. - тут нет, они делаются до этого момента.

Первоначально где-то слизал, потом перепилил. Где - уже не вспомню, очень уж давно это было.

P.S. Меня до сих пор удивляет, что таких вещей нет в базовой поставке.
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017609
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vizit0rP.S. Меня до сих пор удивляет, что таких вещей нет в базовой поставке.

Какие преимущества оно даёт по сравнению с TFileStream?
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017612
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Угу. Я тоже не понимаю зачем в реальной жизни нужны "маппированные" файлы.
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017613
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSerКакие преимущества оно даёт по сравнению с TFileStream?

Никаких.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017617
Фотография Ежов Дмитрий Сергеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне надо, чтобы файлик записался, даже несмотря на то, что процесс умер.
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017618
Фотография Ежов Дмитрий Сергеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нашел компонент с Торри по ссылке выше, допилил под использование с файлами, созданными через CreateFile, а не просто область в памяти, все заработало.
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017619
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat
Угу. Я тоже не понимаю зачем в реальной жизни нужны "маппированные" файлы.

На самом деле, именно в реализации TStream - пользы никакой, а вообще если работать через API, то доступ будет быстрее т.к., как я понимаю, MapViewOfFile() тупо возвращает адрес данных в файловом кэше и исключается лишнее копирование памяти туда-сюда, особенно в случае последовательного доступа.
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017620
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ежов Дмитрий Сергеевич
Мне надо, чтобы файлик записался, даже несмотря на то, что процесс умер.

Это можно решить через FlushFileBuffers после записи данных
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017622
Фотография Ежов Дмитрий Сергеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,

Это может решить только венда. Никаких FlushBuffer нет, процесс умер.
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017623
Фотография Ежов Дмитрий Сергеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На самом деле, маппированный файл глубоко используется в нашей 1С-очке.
https://its.1c.ru/db/metod8dev/content/5860/hdoc

Пользователи сидят клиентами на серверном процессе rphost, который хранит всю их актуальную инфу в сеансовых данных, по факту в памяти. Серверный процесс падает (либо его рубит админ), менеджер сервера обнаруживает это, создает новый серверный процесс, который подтягивает сеансовые, которые уже записала венда.
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017629
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpкак я понимаю, MapViewOfFile() тупо возвращает адрес данных в файловом кэше

Судя по "A mapped view of a file is not guaranteed to be coherent with a file that is
being accessed by the ReadFile or WriteFile function." это не так.

Ежов Дмитрий СергеевичМне надо, чтобы файлик записался, даже несмотря на то, что процесс умер.

Тогда просто всегда пиши WriteLn в паре с Flush.

Ну или почини процесс, чтобы не умирал.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017631
Фотография Ежов Дмитрий Сергеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
мммм, неумирающий серверный процесс в сложных системах, без утечек памяти и кривых сторонних компонентов и кривого легаси от девопса. Что может быть естественней...
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017636
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ежов Дмитрий СергеевичЧто может быть естественней...

Использование инструментов тестирования и культуры программирования. Кто из дельфинов
нынче на это способен?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017652
Vizit0r
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer
Vizit0rP.S. Меня до сих пор удивляет, что таких вещей нет в базовой поставке.


Какие преимущества оно даёт по сравнению с TFileStream?

насколько я помню из результатов изначального сравнения - MMF дает большой прирост к скорости непоследовательного чтения (записи нет). Ну и плюс доступ по указателю упрощает код.
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017658
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

Судя по "A mapped view of a file is not guaranteed to be coherent with a file that is
being accessed by the ReadFile or WriteFile function." это не так.

Вообще не вижу взаимосвязи.
ReadFile читает данные в буфер и после этого они там не меняются, при изменении файла.
MMF, как я понимаю, отображает всё в живую.
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017667
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpВообще не вижу взаимосвязи.
ReadFile читает данные в буфер и после этого они там не меняются, при изменении файла.

WriteFile пишет данные с системный буфер. Если бы этот буфер отображался сразу на память -
данные в нём должны всегда соответствовать тому, что записало WriteFile. И наоборот: что
записано в MMF, всегда должно получиться из ReadFile.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017670
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ежов Дмитрий Сергеевич
мммм, неумирающий серверный процесс в сложных системах, без утечек памяти и кривых сторонних компонентов и кривого легаси от девопса. Что может быть естественней...
Даже если так, хранить важные данные надо в транзакционно безопасной среде.
...
Рейтинг: 0 / 0
Файлы, отображаемые в память.
    #40017696
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ежов Дмитрий Сергеевич
Мне надо, чтобы файлик записался, даже несмотря на то, что процесс умер.
если у вас программа обвалится на каком-то "странном" состоянии, файлы, отображаемые в память, в этом случае не помогут

Ежов Дмитрий Сергеевич
alekcvp,

Это может решить только венда. Никаких FlushBuffer нет, процесс умер.
это не цель FlushBuffer, его цель - зафиксировать какое-то "устойчивое" состояние. Если операция прошла, то как минимум, она зафиксирована в журнале файловой системы
например, классический подход - это "ведение журнала операций + периодическое сохранение всего состояния"

в случае обвала
1. берётся последнее сохранённое состояние,
2. ищется запись в журнале, которая соответствует этому состоянию, и накатываются все операции, сохранённые в журнале после неё

NTFS, кстати, практически по такому же принципу работает
...
Рейтинг: 0 / 0
25 сообщений из 57, страница 1 из 3
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Файлы, отображаемые в память.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]