2012-04-18 3 views
2

나는 내가이 -. 무료 파스칼 나사로 또는 델파이

왜, 어떻게 내가 줄께 그냥 바로 뛰어

의 설명과 함께 보어 사람 원하지 ​​않는 미가공 바이트 데이터를 포함한 바이트 배열. 배열은 1000 바이트입니다. 나는 1000 바이트 배열을 살펴보고 파일 이름과 비슷한 UTF-16 유니 코드 문자 만 추출하려고하지만 정확히 1000 바이트 배열에서 문자가 나타나는 위치를 정확히 알지 못합니다.

나는 Lazarus Unicode Pagethis을 읽었지 만, 내 문제에 대한 구문 론적 접근 방식은 여전히 ​​확실하지 않습니다. 유니 코드 문자는 최대 4 바이트까지 가능하지만 일반적으로 2 문자 (문자 및 공백)임을 이해합니다.

나는 특정 유니 코드 문자가 나에 대해 물어 지금 해결 this thread에 더 존재 알고 다른 분야에 대한 성공 UTF8encode (WideCharLenToString를 (@ 경우 MyArray, SomeIntValue) 사용했습니다.하지만 지금은 "사냥"필요 다른 이유로, 배열 내에서. 예 : "처음 16 바이트를 살펴 봅니다. 유니 코드입니까? 그렇지 않으면 다음 16을보십시오. 유니 코드입니까? 그렇다면 문자열로 변환하고".

이 사람이 나를 도울 수 있습니까?

답변

5

를 바이트의 실제 레이아웃이나 파일 이름의 형식을 모른 채 (드라이브 문자가 않습니다 경로, UNC 경로를 사용합니까? 아니면 파일 이름입니까?), 파일 이름 문자열의 경계를 찾아 다니는 것은 어려울 것입니다.

파일 이름이 항상 드라이브 문자와 경로로 시작된다고 가정하면 'a' 사이의 문자로 구성된 6 바이트 UTF-16 시퀀스를 디코딩 할 때까지 한 번에 한 바이트 씩 루프를 반복 할 수 있습니다. 'z' 또는 'A' - 'Z' 다음에 ':''\' 문자가옵니다.

var 
    Buffer: array[0..1000-1] of Byte; 
    I: Integer; 
    PCh: PWord; 
    Hi, Lo: Word; 
    Ch: Cardinal; 
    PStart: PWideChar; 
    Len: Integer; 
    FileName: WideString; 
begin 
    ... 

    I := 0; 
    while I <= (SizeOf(Buffer)-6) do 
    begin 
    PCh := PWord(@Buffer[I]); 
    if not (((PCh^ >= Ord('a')) and (PCh^ <= Ord('z'))) or ((PCh^ >= Ord('A')) and (PCh^ <= Ord('Z')))) then 
    begin 
     Inc(I); 
     Continue; 
    end; 
    Inc(PCh);  
    if PCh^ <> Ord(':') then 
    begin 
     Inc(I); 
     Continue; 
    end; 
    Inc(PCh); 
    if PCh^ <> Ord('\') then 
    begin 
     Inc(I); 
     Continue; 
    end; 
    PStart := PWideChar(@Buffer[I]); 
    Len := 0; 
    Inc(I, 6); 
    Inc(PCh); 
    while I <= (SizeOf(Buffer)-2) do 
    begin 
     if (PCh^ < $D800) or (PCh^ > $DFFF) then 
     begin 
     Ch := Cardinal(PCh^); 
     Inc(I, 2); 
     if Ch = 0 then Break; 
     Inc(Len); 
     end else 
     begin 
     if PCh^ > $DBFF then Break; 
     if (I+2) = SizeOf(Buffer) then Break; 
     Hi := PCh^; 
     Inc(PCh); 
     if (PCh^ < $DC00) or (PCh^ > $DFFF) then Break; 
     Lo := PCh^; 
     Ch := ((Cardinal(Hi) - $D800) * $400) + (Cardinal(Lo) - $DC00) + $10000; 
     if Ch > $10FFFF then Break; 
     Inc(I, 4); 
     Inc(Len, 2); 
     end; 
    end; 
    SetString(FileName, PStart, Len); 
    if Len > 0 then 
    begin 
     ... use FileName as nedeed... 
    end; 
    end; 
    ... 
end; 
0

UTF-16 코드 포인트 중 하나를 2 바이트입니다 : 당신이 찾아내는 경우에 당신이 디코딩 널 문자 또는 유효한 UTF-16 순서가 아닌 이진 값, 예를 들면 발생할 때까지, 디코딩 UTF-16 시퀀스를 유지 4 바이트 길이. 그것은 편지가 아니라 공간입니다. 고립되어 대부분의 16 비트 단어는 유효한 UTF-16 문자입니다. (D800과 DBFF 사이의 값을 가진 코 포인트는 하나의 완전한 유니 코드 문자를 만들기 위해 DC00-DFFF 범위의 값이 뒤따라야합니다.) 유효한 UTF-16을 찾고 있다면, 많은 어려움을 겪을 것 같지 않습니다. .ext (UTF-16으로 \ 00e \ 00e \ 00x \ 00t 또는. \ 00e \ 00x \ 00t \ 00으로 인코딩됩니다.) 여부에 따라 파일 이름에있는 특정 패턴을 찾아야합니다. 빅 엔디안 또는 리틀 엔디안)

관련 문제