powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Косяк при чтении CLOB`а
16 сообщений из 16, страница 1 из 1
Косяк при чтении CLOB`а
    #39602899
Леонов Юрий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день всем гуру.
Бьюсь второй день, не могу найти проблему. Но по сути.
Стоит задача выгрузить из БД данные в *.csv файл. Но не просто выгрузить данные, а добавить заголовки столбцов и итоги по некоторым полям. Заголовки и итоги записываю руками, проблем нет при отображении. А вот данные... Данные формируются PL\SQL функцией, которая возвращает clob. В Delphi я его частями записываю в FileStream. Но вот только записывается ерунда, кракозябры какие-то. И строк в 2 раза меньше чем надо. Код прилагаю

Код: 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.
159.
160.
161.
162.
163.
procedure ExportGridToCSV(ATableView: TcxGridDBTableView;
  ASession: TOracleSession; AParam: TParamList);
const
  cBuffSize = 50000;
var
  I, LType, J: Integer;
  LSQLText: string;
  LPkMop: TPkMop;
  LLob: TLOBLocator;
  LSaveDialog: TSaveDialog;
  LTableName, LWhereText, LOrderText, LVal: string;
  LHandle: THandle;
  LChar: char;
  LText, LFormat, LLobStr: string;
  LLength: DWORD;
  LBuff: array[1..cBuffSize] of AnsiChar; //для Byte таже песня
  LIsFooter: Boolean;
  LCount, LStartRow, LRowCount, LEndRow, LLenClob: Integer;
  LReadCount: Integer;
  LStream: TFileStream;
  function TimeToName(ADate: TDateTime): string;
  begin
    Result := FormatDateTime('_YYYYMMDDHHNNSS', ADate);
  end;
begin
  LCount := StrToInt(AParam.GetParam('COUNT'));
  LTableName := AParam.GetParam('TABLE_NAME');
  LWhereText := AParam.GetParam('WHERE');
  LOrderText := AParam.GetParam('ORDER');
  LSaveDialog := TSaveDialog.Create(nil);
  try
    LSaveDialog.InitialDir := AppContext.AppDir.ExportDir;
    LSaveDialog.FileName := ATableView.Name + TimeToName(Now) + '.csv';
    LSaveDialog.Filter := 'CSV|*.csv';
    try
      if LSaveDialog.Execute then
      begin
          LPkMop := TPkMop.Create(nil);
          LPkMop.Session := ASession;
          LLob := TLOBLocator.Create(ASession, otBLOB);
          for I := 0 to ATableView.ColumnCount - 1 do
          begin
            if ATableView.Columns[I].Visible then
            begin
              case ATableView.Columns[I].DataBinding.Field.DataType of
                ftInteger:
                  LType := 1;
                ftFloat:
                  if (Assigned(ATableView.Columns[I].Properties) and
                    (ATableView.Columns[I].Properties is TcxCurrencyEditProperties)) then
                    LType := 4
                  else
                    LType := 1;
                ftDate, ftDateTime:
                  LType := 3;
                ftString:
                  LType := 2;
              end;
              if I = 0 then
              begin
                if LType = 4 then
                  LSQLText := #39 + '"' + #39 + ' || nvl(t.' +
                    ATableView.Columns[I].DataBinding.FieldName + ', 0) || ' +
                    #39 + '"' + #39
                else
                  LSQLText := #39 + '"' + #39 + ' || t.' + ATableView.Columns[I]
                    .DataBinding.FieldName + ' || ' + #39 + '"' + #39;
              end
              else
              begin
                if LType = 4 then
                  LSQLText := LSQLText + ' || chr(9) || ' + #39 + '"' + #39 +
                    ' || nvl(t.' + ATableView.Columns[I].DataBinding.FieldName +
                    ', 0) || ' + #39 + '"' + #39
                else
                  LSQLText := LSQLText + ' || chr(9) || ' + #39 + '"' + #39 +
                    ' || t.' + ATableView.Columns[I].DataBinding.FieldName +
                    ' || ' + #39 + '"' + #39;
              end;
            end;
          end;
          try
            LStream := TFileStream.Create(LSaveDialog.FileName, fmCreate);

            // добавляем признак что это Unicode
            LChar := chr(65279);
            LStream.WriteBuffer(LChar, 2);
            // добавляем заголовки столбцов
            LInfoPanel.SetCaption('Формуємо шапку...');
            for I := 0 to ATableView.ColumnCount - 1 do
            begin
              if ATableView.Columns[I].Visible then
                LText := LText + chr(9) + '"' + ATableView.Columns[I]
                  .Caption + '"';
            end;
            Delete(LText, 1, 1);
            LText := LText + #13#10;
            LStream.WriteBuffer(LText[1], Length(LText) * 2);

            LSQLText := 'select ' + LSQLText +
              ' || chr(13) || chr(10) as val from ' + LTableName + ' t';
            if Length(Trim(LWhereText)) > 0 then
              LSQLText := LSQLText + ' where ' + LWhereText;
            if Length(Trim(LOrderText)) > 0 then
              LSQLText := LSQLText + ' order by ' + LOrderText;

            LLob := LPkMop.ExportGridToCSVFull_0(LSQLText);
            SetLength(LBuff, cBuffSize*2);
            LInfoPanel.SetCaption('Зберігаємо дані...');
            if not LLob.IsNull then
            begin
              repeat
                LReadCount := LLob.Read(LBuff[1], cBuffSize);
                LStream.WriteBuffer(LBuff[1], LReadCount);
              until LReadCount < cBuffSize;
            end;
            LText := '';
            for I := 0 to ATableView.ColumnCount - 1 do
            begin
              if ATableView.Columns[I].Visible then
              begin
                LText := LText + chr(9) + '"';
                with ATableView.DataController.Summary do
                begin
                  for J := 0 to FooterSummaryItems.Count - 1 do
                  begin
                    if ((FooterSummaryItems[J] as TcxGridDBTableSummaryItem)
                      .Column = ATableView.Columns[I]) then
                    begin
                      LText := LText + VarToStr(FooterSummaryValues[J]);
                      Break;
                    end;
                  end;
                  LText := LText + '"';
                end;
              end;
            end;
            Delete(LText, 1, 1);
            LText := LText + #13#10;
            LStream.WriteBuffer(LText[1], Length(LText) * 2);
          finally
            LStream.Free;
          end;
        if MessageDlg('Відкрити збережений файл?', mtConfirmation,
          [mbYes, mbNo], 0, mbYes) = mrYes then
          ShellExecute(Application.MainForm.Handle, nil,
            PChar(LSaveDialog.FileName), nil, nil, SW_RESTORE)
        else
          Application.MainForm.Handle;
      end;
    except
      on E: Exception do
        Application.ShowException(E);
    end;
  finally
    if Assigned(LLob) then
      FreeAndNil(LLob);
    if Assigned(LPkMop) then
      FreeAndNil(LPkMop);
    if Assigned(LSaveDialog) then
      FreeAndNil(LSaveDialog);
  end;
end;


В итоге открываю файл, там первая и последняя строки нормальные, все что между ними - китайские иероглифы. Ну и сам вопрос:
Как правильно записать данные? Спасибо
...
Рейтинг: 0 / 0
Косяк при чтении CLOB`а
    #39602920
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Леонов ЮрийДанные формируются PL\SQL функцией, которая возвращает clob

Уже смешно.

А NLS_LANG у тебя как выставлен?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Косяк при чтении CLOB`а
    #39602952
Леонов Юрий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

RUSSIAN_RUSSIA.CL8MSWIN1251
...
Рейтинг: 0 / 0
Косяк при чтении CLOB`а
    #39602960
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Леонов Юрийдобавляем признак что это Unicode
Леонов ЮрийRUSSIAN_RUSSIA.CL8MSWIN1251
ЧиТД.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Косяк при чтении CLOB`а
    #39602967
Леонов Юрий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovЧиТД.


Я не сведущ в этих аббревиатурах
...
Рейтинг: 0 / 0
Косяк при чтении CLOB`а
    #39602973
ma1tus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Леонов Юрий,

если данные уже на клиенте, в датасете и "в гриде", зачем их извлекать повторно?
...
Рейтинг: 0 / 0
Косяк при чтении CLOB`а
    #39602974
Леонов Юрий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
при
Код: pascal
1.
LBuff: array[1..cBuffSize] of AnsiChar;

в дебаговом режиме данные читаются из TLobLocator правильно в буффер, но при открытии сформированного файла идут кракозябры.
...
Рейтинг: 0 / 0
Косяк при чтении CLOB`а
    #39603016
DesWind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Леонов Юрий,
Дык, есно будет не пойми-что, если ты смешиваешь в кучу Unicode и Ansi
...
Рейтинг: 0 / 0
Косяк при чтении CLOB`а
    #39603019
DesWind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Леонов Юрий,

И для упрощения кода посмотри класс TWriter
...
Рейтинг: 0 / 0
Косяк при чтении CLOB`а
    #39603021
Леонов Юрий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DesWind,

если беру массимв Byte или Char то результат не меняется
...
Рейтинг: 0 / 0
Косяк при чтении CLOB`а
    #39603023
Леонов Юрий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DesWind,

я даже брал обычный
Код: pascal
1.
2.
3.
LHandle := CreateFile(PChar(LSaveDialog.FileName), GENERIC_WRITE, 0, nil, OPEN_ALWAYS, 0, 0);
...
WriteFile(LHandle, LChar, 2, LLength, nil);



результат одинаковый.
...
Рейтинг: 0 / 0
Косяк при чтении CLOB`а
    #39603032
DesWind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Леонов Юрий,

У тя данные в анси, ты их буфером, без преобразования копируешь в юникод, и что ты на выходе желаешь получить?
...
Рейтинг: 0 / 0
Косяк при чтении CLOB`а
    #39603038
DesWind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если нет специфических требований, то для начала поменяй все на AnsiString и AnsiChar, с соответствующими правками в коде.
...
Рейтинг: 0 / 0
Косяк при чтении CLOB`а
    #39603141
Леонов Юрий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DesWind,

я же говорю мозги закипели((

Спасибо большое, помогло
...
Рейтинг: 0 / 0
Косяк при чтении CLOB`а
    #39603150
Леонов Юрий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
поменял, получилось такое:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
procedure ...
var
  ...
  LBuff: AnsiString;
  LStrBuff: string;
  ...
begin
  ...
  SetLength(LBuff, cBuffSize*SizeOf(AnsiChar));
  if not LLob.IsNull then
  begin
    repeat
      LReadCount := LLob.Read(Pointer(LBuff)^, cBuffSize*SizeOf(AnsiChar));
      LStrBuff := LBuff;
      LStream.WriteBuffer(Pointer(LStrBuff)^, Length(LStrBuff) * SizeOf(Char));
    until LReadCount < cBuffSize;
  end;
  ...
end;



Результат - тот что нужно
...
Рейтинг: 0 / 0
Косяк при чтении CLOB`а
    #39603294
vavan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovЛеонов ЮрийДанные формируются PL\SQL функцией, которая возвращает clob

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


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