Delphi: строки в записях больше 255 символов

Есть ли способ получить строки в записях больше 255 символов?

ИЗМЕНИТЬ:

У меня есть что-то вроде следующего:

TQuery = Record
  Action: string[255];
  Data: string;
end;

если я сейчас скажу:

Test: TQuery;
Test.Data := 'ABCDEFGHIJKLMN...up to 255...AISDJIOAS'; //Shall be 255 chars

Не работает, а компилятор ругается... Как это исправить?


person Acron    schedule 28.07.2009    source источник


Ответы (5)


Если вы хотите иметь возможность записывать свою запись в файл, вы можете определить свою строку, например, как массив ansichar. После этого вы можете обращаться с ним как со строкой.

Пример:

program StrInRecTest;
{$APPTYPE CONSOLE}
uses SysUtils;

type
  TStringRec=
    packed record
        S:array[0..1023] of ansichar;
    end;

var
  StringRec:TStringRec;
  F:File of TStringRec;
begin
  StringRec.S := 'Hello';
  WriteLn(StringRec.S);
  WriteLn('First char is:'+StringRec.S[0]); // watch out with this


  // now let's try saving this to a file and reading it back...

  // make a long string with x-es
  FillChar(StringRec.S,Length(StringRec.S),'X');
  StringRec.S[High(StringRec.S)] := #0; // terminate the string

  WriteLn(StringRec.S);

  // write to a file
  AssignFile(F,'tmp.txt');
  ReWrite(F);
  Write(F,StringRec);
  CloseFile(F);

  WriteLn;

  // read from file
  AssignFile(F,'tmp.txt');
  Reset(F);
  Read(F,StringRec);
  CloseFile(F);

  WriteLn(StringRec.S); // yay, we've got our long string back

  ReadLn;
end.
person Wouter van Nifterick    schedule 28.07.2009

Delphi и три строки

Давным-давно, на заре Паскаля, там были короткие строки. Они состояли из блока байтов с максимальным размером 256. Первый байт был байтом длины:

5, H, e, l, l, o

Вы можете определить строки фиксированной длины для экономии памяти:

a: string[5];

Windows использует строки C, которые представляют собой указатель на блок памяти, оканчивающийся символом 0. Эти строки не ограничены 255 байтами. Сначала они представлены как PChar (указатель на char). Но позже строка по умолчанию была интерпретирована как строка типа C. Вы все еще можете использовать короткие строки:

a: string[22];
b: ShortString;
c: string; // C (Delphi) string

В Delphi 2009 был представлен Unicode. Теперь каждая строка была строкой Unicode. Это указатель на часть памяти, содержащую символы Юникода. У нас все еще есть тип ShortString. К старым строкам ansi можно было получить доступ с помощью AnsiString или PAnsiChar.

Теперь, когда строки являются указателями, нет ограничений на размер. Но строковые литералы по-прежнему ограничены 255 символами.

person Toon Krijthe    schedule 28.07.2009
comment
хороший рассказ! Вы заметили, что ОП специально спросил о записях? Вы не употребили это слово! :-) - person Argalatyr; 29.07.2009

Обычно да. Вам не нужно делать что-то особенное, если вы используете обычный тип String (или другие типы длинных строк), а не ShortString.

type
  TMyRec = record
    Value: string;
  end;

На практике это зависит от того, что вы хотите делать с записью. Если вы хотите заблокировать запись чего-либо в файл или предоставить запись функции DLL, вам нужно переключиться на массивы символов:

type
  TMyRec = record
    Value: array[0..1023] of Char;
  end;
person Daniel Rikowski    schedule 28.07.2009
comment
Я думаю, что это будет проблематично, когда в игру вступит что-то вроде файла записи. - person Uwe Raabe; 28.07.2009

В Delphi есть разные типы строк:

  • ShortString — до 255 символов
  • AnsiString — до 2^31 символов
  • WideString — до 2^31 WideChars

строка обычно интерпретируется как AnsiString. AnsiString и WideStrings на самом деле являются указателями на память, в которой хранится строка. Компилятор творит там магию для экономии ресурсов.

Таким образом, включение строки в запись может дать желаемый результат, но я предполагаю, что оператор sizeof в записи не сработает.


Спасибо Smasher за указание на это: это цитируется из справки Delphi 2006. Различные версии Delphi могут вести себя по-разному.

person Tobias Langner    schedule 28.07.2009
comment
SizeOf подсчитывает длину указателя. Вам нужна функция Length, чтобы получить длину строки. - person Toon Krijthe; 28.07.2009
comment
string обычно интерпретируется как AnsiString. Это неверно для Delphi 2009, где String интерпретируется как строка Unicode. - person jpfollenius; 29.07.2009

Если вы имеете в виду сохранение его в базе данных, то это полностью зависит от используемой вами базы данных. Некоторые базы данных поддерживают строки длиной до 8 КБ; а SQL 2005 представил varchar(MAX), который имеет ограничение, я полагаю 2 ГБ. MySql 5, похоже, ограничен примерно 65 КБ для того же типа данных.

Однако некоторые из старых позволяют использовать только [var]char(255).

Что вы пытаетесь вставить?

person NotMe    schedule 28.07.2009
comment
я говорю: выберите * из Orders и получите в ответ огромную строку. - person Acron; 28.07.2009
comment
Тогда похоже, что ваша БД поддерживает это. Можете ли вы определить проблему, которая у вас есть немного дальше? Например, вы получаете сообщение об ошибке при попытке обновить эту запись? - person NotMe; 28.07.2009
comment
запись в этом контексте является Pascal структурированным типом, и не имеет ничего общего с базами данных. (Похожим образом, моя машина и Мона Лиза не имеют ничего общего друг с другом, хотя на них обоих есть краска :) - person Reversed Engineer; 04.01.2017
comment
@DaveBoltman: Если вы посмотрите на первоначальный вопрос до редактирования и комментарии ОП к моему ответу, вы увидите, что он изначально извлекал данные из БД. В любом случае, этому делу почти 8 лет... - person NotMe; 05.01.2017