Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Чтение строк в TStringList в полях которых есть перевод строки  [new]
hlopotun
Member

Откуда:
Сообщений: 204
Всем доброго дня,

есть csv со строками, примерно такого вида:

"Field1";"Field2";"Field3";"Field4"
"123";"345
577
789";"abcd";"ttttt"
"654";"555";"aaaa";"bbbb"

в некоторых полях встречается перевод строки.
Читаю так:
 CsvStr := TStringList.Create;
     CsvStr.StrictDelimiter := True; // на случай если не будет QuotedChar (но в даннон случае он есть)
     CsvStr.Delimiter := ';';
     CsvStr.QuoteChar := '"';
     CsvStr.LineBreak := '"'+sLineBreak;

CsvStr.DelimitedText := sStr; // с содержимым файла

всёравно разбивка на строки происходит по переводу строки.
Всё уже перепробовал, не пойму где ошибаюсь.
Посоветуйте чтото.

Спасибо.
23 фев 21, 14:27    [22285138]     Ответить | Цитировать Сообщить модератору
 Re: Чтение строк в TStringList в полях которых есть перевод строки  [new]
Cobalt747
Member

Откуда:
Сообщений: 2282
Рекомендую пройти отладкой по методу TStrings.SetDelimitedText - там вы все увидите сами
23 фев 21, 14:32    [22285140]     Ответить | Цитировать Сообщить модератору
 Re: Чтение строк в TStringList в полях которых есть перевод строки  [new]
DHDD
Member

Откуда:
Сообщений: 47
hlopotun,

https://blogs.embarcadero.com/super-fast-csv-files-processing-with-winsoft-csv-library/
23 фев 21, 15:00    [22285155]     Ответить | Цитировать Сообщить модератору
 Re: Чтение строк в TStringList в полях которых есть перевод строки  [new]
hlopotun
Member

Откуда:
Сообщений: 204
Cobalt747,

странно, LineBreak в коде даже не упоминается ...
+

procedure TStrings.SetDelimitedText(const Value: string);
var
  P, P1: PChar;
  S: string;
begin
  BeginUpdate;
  try
    Clear;
    P := PChar(Value);
    if not StrictDelimiter then
      while (P^ in [#1..' ']) do
        P := NextChar(P);
    while P^ <> #0 do
    begin
      if (P^ = QuoteChar) and (QuoteChar <> #0) then
        S := AnsiExtractQuotedStr(P, QuoteChar)
      else
      begin
        P1 := P;
        while ((not StrictDelimiter and (P^ > ' ')) or
              (StrictDelimiter and (P^ <> #0))) and (P^ <> Delimiter) do
          P := NextChar(P);
        SetString(S, P1, P - P1);
      end;
      Add(S);
      if not StrictDelimiter then
        while (P^ in [#1..' ']) do
          P := NextChar(P);

      if P^ = Delimiter then
      begin
        P1 := P;
        if NextChar(P1)^ = #0 then
          Add('');
        repeat
          P := NextChar(P);
        until not (not StrictDelimiter and (P^ in [#1..' ']));
      end;
    end;
  finally
    EndUpdate;
  end;
end;


значит это что DelimetedText даже нет смысла использовать.
Я тут пример немного упростил, на самом деле читается через LoadFromFile,
а он судя по исходнику использует SetTextStr в котором LineBreak уже присутствует:
+

procedure TStrings.LoadFromFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
LoadFromStream(Stream);
finally
Stream.Free;
end;
end;

procedure TStrings.LoadFromStream(Stream: TStream);
begin
LoadFromStream(Stream, nil);
end;

procedure TStrings.LoadFromStream(Stream: TStream; Encoding: TEncoding);
var
Size: Integer;
Buffer: TBytes;
begin
BeginUpdate;
try
Size := Stream.Size - Stream.Position;
SetLength(Buffer, Size);
Stream.Read(Buffer, 0, Size);
Size := TEncoding.GetBufferEncoding(Buffer, Encoding, FDefaultEncoding);
SetEncoding(Encoding); // Keep Encoding in case the stream is saved
SetTextStr(Encoding.GetString(Buffer, Size, Length(Buffer) - Size));
finally
EndUpdate;
end;
end;

procedure TStrings.SetTextStr(const Value: string);
var
P, PCurVal, PCurLB, PStartVal, PStartLB, PEndLB: PChar;
S: string;
LineBreakLen: Integer;
begin
BeginUpdate;
try
Clear;
P := Pointer(Value);
if P = nil then
Exit;

LineBreakLen := Length(LineBreak);
if LineBreakLen = 0 then
begin
Add(Value);
Exit;
end;

// When LineBreak is:
// * sLineBreak - for compatibility with Windows, Posix and old macOS platforms,
// we handle #13#10, #10 and #13 as it would be #13#10.
// * NOT sLineBreak - we use strict checking for LineBreak.
if CompareStr(LineBreak, sLineBreak) = 0 then
begin
while P^ <> #0 do
begin
PStartVal := P;
while not (P^ in [#0, #10, #13]) do Inc(P);
SetString(S, PStartVal, P - PStartVal);
Add(S);
if P^ = #13 then Inc(P);
if P^ = #10 then Inc(P);
end;
Exit;
end;

PStartLB := Pointer(LineBreak);
PEndLB := PStartLB + LineBreakLen;
PCurLB := PStartLB;
PStartVal := P;

while P^ <> #0 do
begin
while (P^ <> PStartLB^) and (P^ <> #0) do
Inc(P);
if P^ <> #0 then
begin
PCurVal := P + 1;
Inc(PCurLB);
while PCurLB^ <> #0 do
begin
if PCurVal^ <> PCurLB^ then
Break;
Inc(PCurVal);
Inc(PCurLB)
end;
if PCurLB = PEndLB then
begin
SetString(S, PStartVal, P - PStartVal);
Add(S);
P := PCurVal;
PStartVal := P;
end
else
Inc(P);
PCurLB := PStartLB;
end;
end;

if P > PStartVal then
begin
SetString(S, PStartVal, P - PStartVal);
Add(S);
end;
finally
EndUpdate;
end;
end;
23 фев 21, 15:05    [22285163]     Ответить | Цитировать Сообщить модератору
 Re: Чтение строк в TStringList в полях которых есть перевод строки  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 54830
сделать замену в sStr #13#10 на какую-то подстроку вида '{#13#10}'
а потом пробежаться по итемсам и поменять назад

будет помедленнее (
23 фев 21, 16:33    [22285207]     Ответить | Цитировать Сообщить модератору
 Re: Чтение строк в TStringList в полях которых есть перевод строки  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 52449

Какой только фигнёй люди не будут маяться место написания простенького автомата на пару
экранов...

Posted via ActualForum NNTP Server 1.5

23 фев 21, 16:53    [22285217]     Ответить | Цитировать Сообщить модератору
 Re: Чтение строк в TStringList в полях которых есть перевод строки  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 12572
Dimitry Sibiryakov
на пару экранов...
Или я чего-то не понимаю, или тут максимум строчек 20
23 фев 21, 16:56    [22285219]     Ответить | Цитировать Сообщить модератору
 Re: Чтение строк в TStringList в полях которых есть перевод строки  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 54830
_Vasilisk_
Dimitry Sibiryakov
на пару экранов...
Или я чего-то не понимаю, или тут максимум строчек 20
кавычки ещё пощитать же
23 фев 21, 17:04    [22285222]     Ответить | Цитировать Сообщить модератору
 Re: Чтение строк в TStringList в полях которых есть перевод строки  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 12572
andreymx
кавычки ещё пощитать же
Без кавычек Можно уложиться в одну строку
string.Split([';'])
+ 5 строк на цикл чтения файла
23 фев 21, 17:20    [22285230]     Ответить | Цитировать Сообщить модератору
 Re: Чтение строк в TStringList в полях которых есть перевод строки  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 54830
_Vasilisk_
andreymx
кавычки ещё пощитать же
Без кавычек Можно уложиться в одну строку
string.Split([';'])

+ 5 строк на цикл чтения файла
это из более нового, чем мой древний д7?
23 фев 21, 17:37    [22285234]     Ответить | Цитировать Сообщить модератору
 Re: Чтение строк в TStringList в полях которых есть перевод строки  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 12572
andreymx
это из более нового, чем мой древний д7?
Да XE3 (а может и раньше) и новее
23 фев 21, 17:41    [22285237]     Ответить | Цитировать Сообщить модератору
 Re: Чтение строк в TStringList в полях которых есть перевод строки  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 54830
https://www.sql.ru/forum/176889-2/analog-funkcii-split-v-delphi
23 фев 21, 17:44    [22285238]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить