Гость
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / внешние файлы / 6 сообщений из 6, страница 1 из 1
17.02.2016, 13:56
    #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
17.02.2016, 14:14
    #39173178
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
внешние файлы
someonesomeoneможет кто подскажет как правильно высчитать сдвиги полей?
Если не связываться с полями BIGINT, а ограничиться INTEGER, то:
1) Объяви все поля в одной record (ни в коем случае не packed!).
2) Всё, внешний файл это будет file of this_record.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
17.02.2016, 14:51
    #39173231
someonesomeone
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
внешние файлы
Dimitry Sibiryakov,

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

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

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

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


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