2009-03-07 9 views
1

다음과 같은 구조가 디스크에서 저장되고로드되어야합니다.Delphi 2009에서 디스크에 문자열 저장

function 
var F: FILE; 
    Hdr: RSecStructure; 
begin 
... 
BlockWrite (F, Hdr, SizeOf(Hdr)); 
... 
end 

위의 코드는 내가 짧은 사이에 할당 할 때 경고 메시지를 많이 가지고 D2009에서 델파이 7에서 작동 :

RSecStructure= packed record 
    Name    : string[255];  {NEED UNICODE SUPPORT HERE} 
    ScreenName   : string[255]; 
    OrigFileName  : string[255];      
    Prim    : string[255];           
    ParentVersion  : integer; 
    sTag1    : string[255];  
    sTag2    : string[255]; 
    sTag3    : string[255]; 
    sTag4    : string[255]; 
    DateAdd   : TDateTime; 
    DateModify   : TDateTime; 
    end; 

은 지금까지 나는 구조를 저장하기 위해이 같은 것을 사용했다 및 유니 코드 문자열. 지금까지 필자는 컴파일러 경고 또는 힌트가 없어도 Delphi 코드를 작성할 수 있었고 그렇게하고 싶습니다. 그래서 경고를받지 않고 디스크에 문자열 (유니 코드는 중요하지만 중요하지는 않음)을 저장하는 것이 필요합니다.

답변

6

또는 저장 가능한 짧은 유니 코드 문자열 레코드를 선언하고 암시 적 'to 문자열'및 'from 문자열'변환을 구현할 수 있습니다.

program TestShortUnicodeString; 

{$APPTYPE CONSOLE} 

uses 
    SysUtils; 

type 
    TShortUnicodeString = record 
    private 
    Data: array [0..255] of char; //WARNING - NOT initialized to an empty string 
    public 
    class operator Implicit(const sus: TShortUnicodeString): string; inline; 
    class operator Implicit(const ws: string): TShortUnicodeString; inline; 
    end; 

class operator TShortUnicodeString.Implicit(const sus: TShortUnicodeString): string; 
begin 
    Result := StrPas(sus.Data); 
end; 

class operator TShortUnicodeString.Implicit(const ws: string): TShortUnicodeString; 
begin 
    // too long strings are silently truncated 
    StrPLCopy(Result.Data, ws, Length(Result.Data)-1); 
end; 

type 
    TTestRec = record 
    ws1: TShortUnicodeString; 
    ws2: TShortUnicodeString; 
    end; 

var 
    f : file; 
    test1: TTestRec; 
    test2: TTestRec; 

begin 
    test1.ws1 := '6*9 ='; 
    test1.ws2 := ' 42'; 
    AssignFile(f, 'test.dat'); 
    Rewrite(f, 1); 
    BlockWrite(f, test1, SizeOf(test1)); 
    CloseFile(f); 
    AssignFile(f, 'test.dat'); 
    Reset(f, 1); 
    Assert(FileSize(f) = SizeOf(test2)); 
    BlockRead(f, test2, SizeOf(test2)); 
    CloseFile(f); 
    Writeln(string(test2.ws1), string(test2.ws2)); 
    Readln; 
end. 

[위의 코드는 공개 된 것으로 배포되었으며 라이센스 의무가 없습니다.]

+0

'TShortUnicodeString = record'와 같은 것을'string [N]'과 유사하게 쓸 수 있습니까? (나는 테스트 할 D2010이 없습니다.) –

8

문자열 필드는 Delphi 2009에서 모든 이전 버전과 동일합니다. ShortString은 유니 코드 형식이 아닙니다.

따라서 해당 레코드를있는 그대로 사용할 수 있어야합니다.

델파이 7에서 작동한다고 말하십니까? 이 아니고 델파이 2009에서이 작동합니까? 문제에 대해 설명하십시오.

고정 길이 유니 코드를 ShortString과 동일하게 설정한다고 가정합니까? 하나도 없으므로 이와 같은 레코드를 가질 수 없으며 문자열과 같은 유니 코드 값을 보유하고 디스크에 직접 저장할 수 없습니다.

어쨌든 디스크 포맷이 현재 포맷과 호환되지 않기 때문에 큰 문제는 아니라고 생각합니다. 문자가 너무 큽니다.

당신은 문자의 배열 사용할 수 있습니다

type 
    TSecStructure = packed record 
    Name    : array[0..255] of UnicodeChar; 
    ScreenName   : array[0..255] of UnicodeChar; 
    OrigFileName  : array[0..255] of UnicodeChar; 
    Prim    : array[0..255] of UnicodeChar; 
    ParentVersion  : integer; 
    sTag1    : array[0..255] of UnicodeChar; 
    sTag2    : array[0..255] of UnicodeChar; 
    sTag3    : array[0..255] of UnicodeChar; 
    sTag4    : array[0..255] of UnicodeChar; 
    DateAdd   : TDateTime; 
    DateModify   : TDateTime; 
    end; 

실제 문자열 유형과 같은 매우 편리 될 수 없습니다,하지만 대부분의 목적을 위해 작동합니다.

또한 일반 UnicodeString 유형을 사용할 수는 :

type 
    TSecStructure = record 
    Name    : UnicodeString; 
    ScreenName   : UnicodeString; 
    OrigFileName  : UnicodeString; 
    Prim    : UnicodeString; 
    ParentVersion  : integer; 
    sTag1    : UnicodeString; 
    sTag2    : UnicodeString; 
    sTag3    : UnicodeString; 
    sTag4    : UnicodeString; 
    DateAdd   : TDateTime; 
    DateModify   : TDateTime; 
    end; 

당신은 더 이상 디스크에 직접 그 내용을 저장할 수 없습니다,하지만 당신은 더 이상 255 자로 제한하지입니다. 각 문자열 필드를 별도로 저장해야합니다. 문자열의 길이도 저장해야합니다. 또는 나중에 파일을로드 할 시간이되면 문자열이 끝나는 곳과 끝나는 곳을 모를 것입니다.

+0

> 배열 [0..255] of UnicodeChar; 나는 이것이 그렇게 할 것이라고 생각한다. 고마워. – Ampere

+0

이것은 ASCII 문자의 저장 크기를 두 배로 만듭니다. 대신 ShortString을 사용하여 UTF8 문자열을 저장할 수 있습니다 (UTF8Encode, UTF8ToString) –

+0

> ASCII 문자의 저장 크기는 두 배입니다. 괜찮습니다. 감사. – Ampere

2
당신은 파일 형식을 기존의 구조 (문자열 [255]) 기존의 유지조차 제대로 비 유니 코드 이전에 다음과 같은 사용하여 저장된 데이터를 읽을 수 있습니다

:

... 
record.Name:= UTF8EncodeToShortString(Name); 

: 데이터 쓰기 전에

을 데이터를 읽은 후 :

... 
Name:= UTF8ToString(record.Name);