powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / внешние файлы
6 сообщений из 6, страница 1 из 1
внешние файлы
    #39173151
someonesomeone
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
с целью быстрой загрузки данных использую внешние файлы Firebird
для их формирования использую следующий код:

Код: 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.
154.
155.
156.
157.
158.
unit untExtFiles;

interface

const
  MaxRecSize = 65530;
type
  TIBRecord = class
  private
    FLine: array[0..MaxRecSize] of AnsiChar;
    FPos: Integer;
    function GetLine: AnsiString;
  public
    procedure AppendInteger(AValue: Integer);
    procedure AppendSmallInt(AValue: SmallInt);
    procedure AppendFloat(AValue: Int64);
    procedure AppendNumeric(AValue: Int64; Scale: Integer);
    procedure AppendDate(AValue: TDateTime);
    procedure AppendTimeStamp(AValue: TDateTime);
    procedure AppendTime(AValue: TDateTime);
    procedure AppendChar(AValue: AnsiString; ASize: Integer);
    procedure AppendVarChar(AValue: AnsiString; ASize: Integer);
    procedure CheckOffset(ANextSize: Integer; AChar: Boolean);
    procedure Reset;
    constructor Create;
    property Line: AnsiString read GetLine;
    property Pos: Integer read FPos write FPos;
  end;

implementation

procedure TIBRecord.AppendChar(AValue: AnsiString; ASize: Integer);
var
  Tmp: Integer;
begin
  CheckOffset(ASize, True);

  Tmp:= Length(AValue);
  if Tmp > ASize then
    Tmp := ASize;

  SetLength(AValue, ASize);
  FillChar(FLine[FPos], ASize, 32);
  Move(AValue[1], FLine[FPos], Tmp);
  Inc(FPos, ASize);
end;

procedure TIBRecord.AppendDate(AValue: TDateTime);
var
  dInt: Integer;
begin
  CheckOffset(4, False);
  dInt := Trunc(AValue) + 15018;
  Move(dInt, FLine[FPos], 4);
  Inc(FPos, 4);
end;

procedure TIBRecord.AppendFloat(AValue: Int64);
begin
  CheckOffset(8, False);
  Move(AValue, FLine[FPos], 8);
  Inc(FPos, 8);
end;

procedure TIBRecord.AppendInteger(AValue: Integer);
begin
  CheckOffset(4, False);
  Move(AValue, FLine[FPos], 4);
  Inc(FPos, 4);
end;

procedure TIBRecord.AppendNumeric(AValue: Int64; Scale: Integer);
const
  E: array[0..18] of Int64 = (1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,
  10000000000,100000000000,1000000000000,10000000000000,100000000000000,
  1000000000000000,10000000000000000,100000000000000000,1000000000000000000);
var
  dInt: Int64;
begin
  CheckOffset(8, False);
  AValue:= AValue*E[Scale];
  Move(AValue, FLine[FPos], 8);
  Inc(FPos, 8);
end;

procedure TIBRecord.AppendSmallInt(AValue: SmallInt);
begin
  CheckOffset(2, False);
  Move(AValue, FLine[FPos], 2);
  Inc(FPos, 2);
end;

procedure TIBRecord.AppendTime(AValue: TDateTime);
const
  MSecsPerDay10 = 24 * 60 * 60 * 1000 * 10;
var
  dInt: Integer;
begin
  dInt := Trunc(Frac(AValue)*MSecsPerDay10);
  Move(dInt, FLine[FPos], 4);
  Inc(FPos, 4);
end;

procedure TIBRecord.AppendTimeStamp(AValue: TDateTime);
const
  MSecsPerDay10 = 24 * 60 * 60 * 1000 * 10;
var
  dInt: Int64;
begin
  CheckOffset(8, False);
  dInt:= Trunc(AValue) + 15018 + (Trunc(Frac(AValue)*MSecsPerDay10) shl 32);
  Move(dInt, FLine[FPos], 8);
  Inc(FPos, 8);
end;

procedure TIBRecord.AppendVarChar(AValue: AnsiString; ASize: Integer);
var
  Tmp: Integer;
begin
  if (ASize mod 2) = 1 then
    Inc(ASize);

  Tmp:= Length(AValue);
  if Tmp > ASize then
    Tmp := ASize;

  CheckOffset(ASize + 2, True);
  SetLength(AValue, ASize);
  Move(Tmp, FLine[FPos], 2);
  Inc(FPos, 2);
  Move(AValue[1], FLine[FPos], Tmp);
  Inc(FPos, ASize);
end;

procedure TIBRecord.CheckOffset(ANextSize: Integer; AChar: Boolean);
begin
  if (ANextSize mod 4) = 0 then
    Inc(FPos, ANextSize-(FPos mod ANextSize));
end;

constructor TIBRecord.Create;
begin
  Reset;
end;

function TIBRecord.GetLine: AnsiString;
begin
  SetLength(Result, FPos);
  Move(FLine, Result[1], FPos);
end;

procedure TIBRecord.Reset;
begin
  FPos := 0;
  FillChar(FLine, SizeOf(FLine), 0);
end;

end.


проблема в том что не всегда он корректно работает
только в 95% случаев
может кто подскажет как правильно высчитать сдвиги полей?
...
Рейтинг: 0 / 0
внешние файлы
    #39173178
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
someonesomeoneможет кто подскажет как правильно высчитать сдвиги полей?
Если не связываться с полями BIGINT, а ограничиться INTEGER, то:
1) Объяви все поля в одной record (ни в коем случае не packed!).
2) Всё, внешний файл это будет file of this_record.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
внешние файлы
    #39173231
someonesomeone
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov,

а если все-таки BIGINT нужен, то этот вариант не прокатит?
...
Рейтинг: 0 / 0
внешние файлы
    #39173259
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
someonesomeoneа если все-таки BIGINT нужен, то этот вариант не прокатит?
Если он нужен, то придётся выяснять до скольки бит наверх округляется маска NULL-ов и
добавлять соответствующие поля под неё в начало записи. Но file of record уже не
сработает, поскольку сама маска в файл не пишется, придётся писать часть записи, начиная
со значимых полей.

А можно не маяться дурью и приводить всё к CHAR. Тогда не будет проблем ни с
выравниванием, ни с формированием: файл будет выглядеть как обычный текст с фиксированной
шириной колонок.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
внешние файлы
    #39173270
someonesomeone
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov,

спасибо
...
Рейтинг: 0 / 0
внешние файлы
    #39173311
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hello, Dimitry Sibiryakov!
You wrote on 17 февраля 2016 г. 15:56:53:

Dimitry Sibiryakov> А можно не маяться дурью и приводить всё к CHAR.
ну на коне ц то!
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / внешние файлы
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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