各位老大们,问题是这样的,在一个Java写的程序运行中会产生一个日志文件,现在要用Delphi写的程序打开这个日志文件,这时问题就出来了,每次读到一个用UltraEdit打开这个文件并且切换到十六进制编辑模式下十六进制编码显示为“00”的字符就没有办法读取了(这不是空格符,空格符的十六进制编码是“20”),Delphi就好像默认为文件结束了,请问一下高手们怎样才能把带有这样字符(文件中有十六进制编码为“00”的字符)的文件完全读取???
请写出代码,有实例可以发到邮箱:[email protected]
                                [email protected]小弟万分感谢,分不够可以再加。

解决方案 »

  1.   

    我试过了用TStrings和FileOpen方法都不行,每次到哪个十六进制编码为“00”的地方就结束了!我如果把这个“00”改成“20”很容易就通过了,但是程序要求不能修改这个字符,请高手帮帮忙!
      

  2.   

    这是Unicode格式文件,你用TStrings时得转换一下,或者直接用TWideStrings.
      

  3.   

    用 ReadBuffer(var Buffer; Count: Longint);看看 因為00 -> NULL 字符串有一種是以NULL為終結符的 
    ReadBuffer....你想讀多少就是多少 不過實際讀入的是其返回值你可以一次讀定量得數據 或者 一次全部讀完 文件長度可以用 api GetFileSize 獲取。。
      

  4.   

    用AssignFile+readln或TFilestream类应该可以啊
      

  5.   

    Delphi的字符串类型string可以包含#0,但TStringList并不能正确处理包含#0的文本,会在#0处截断该字符串。因此若要读取包含#0的文本可以使用TFileStream。var
      Stream: TStream;
      S: string;
    begin
      Stream := TFileStream.Create('C:\1.txt', fmOpenRead);
      SetLength(S, Stream.Size);
      Stream.Read(S[1], Stream.Size);  // 字符串S即为完整的文本文件内容。
      Stream.Free;
    end;
      

  6.   

    用流可以读任何文件
    用TFilestream
      

  7.   

    Jave 用的是 Unicode 吗? 那么试试这个:function GetFileText(const FileName: string): string;
    var
      hFile: DWORD;
      iSize: DWORD;
      sTemp: string;
    begin
     // 打开文件
      hFile := CreateFile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); // 文件大小
      iSize := GetFileSize(hFile, nil); // 申请内存
      SetLength(sTemp, iSize + 2); // 读入文件
      ReadFile(hFile, sTemp[1], iSize, iSize, nil); // 关闭文件
      CloseHandle(hFile); // 置结束符
      sTemp[iSize + 1] := #0;
      sTemp[iSize + 2] := #0; // 编码格式 
      if (sTemp[1] = #$FF) and (sTemp[2] = #$FE) then // UNICODE
      begin
       // 申请内存
        SetLength(Result, iSize);
       // 转换编码
        WideCharToMultiByte(CP_ACP, 0, PWideChar(@sTemp[3]), -1, @Result[1], iSize, nil, nil);
      end else
        Result := sTemp; // 去除多余
      Result := string(PChar(Result));
    end;
      

  8.   

    谢谢这么多的热心人,不过上面的方法还是不行!具体的测试办法是我用UE在十六进制编辑模式下写下下面的内容“31 00 00 00 00 00 32”,这里“31”就是字符1,“32”就是字符2,我用了上面的办法都只能读出第一个字符,就是“1”这个字符,后面的“2”就怎么也读不出来!我现在的要求就是要读出这些所有的字符,以这种方式(“1     2”)显示出来!
        因为这个用Java程序生成的日志文件中有许多地方都有这种编码显示,我必须得让他们全部读出来!继续等待中.......
      

  9.   

    //参考如下代码
    procedure TForm1.Button1Click(Sender: TObject);
    const
      cNullChar: Char = '?';
    var
      S: string;
      I: Integer;
    begin
      with TMemoryStream.Create do try
        LoadFromFile('c:\temp\temp.log');
        if Size <= 0 then Exit;
        SetLength(S, Size);
        Read(S[1], Size);
        for I := 1 to Length(S) do
          case S[I] of
            #0..#8, #14..#31: S[I] := cNullChar;
          end;
      finally
        Free;
      end;
      Memo1.Text := S;
    end;
      

  10.   

    TO: huaneww(向往牛人) 
    我上面的程序是试过的,TFileStream什么都可以读出来,不可能有读不出的情况。
    之所以你以为没有读出来,是因为你读出来之后企图拿到Memo或者RichEdit中显示,那是不可能显示完整的。还是我那段程序,你创建一个文本文件 C:\1.txt,用UE在十六进制编辑模式下写“31 00 00 00 00 00 32”并保存。
    var
      Stream: TStream;
      S: string;
    begin
      Stream := TFileStream.Create('C:\1.txt', fmOpenRead);
      SetLength(S, Stream.Size);
      Stream.Read(S[1], Stream.Size);  // 字符串S即为完整的文本文件内容。
      Stream.Free;    <-- 把断点设在这里看S的值,你就明白了。
      ShowMessage(S);                  // 这句为了使Delphi的优化不得提早释放S
    end;
      

  11.   

    谢谢DDGG(叮叮当当),真对不起我没有认真看,不过这里转换也遇到了些麻烦,因为文件比较大(都在50M以上),而且文中出现“00”编码的地方都不固定,我想请问一下,用什么方法能快速处理呀!S := StringReplace(S,#0,'^',[rfReplaceAll]);我用这样转换,好像没用呀,转换出来还是把“00”后面的字符去掉了~~~
      

  12.   

    StringReplace也没法正确处理包含#0的串,给你写了一个高效的函数,你可以试试。不过如果真是50M以上的文件,你替换好了也没法直接拿到Memo里显示呀,太大了,恐怕只能每次取一部分显示了。procedure ReplaceZeroStr(var S: string; Len: Integer; A: Char);
    asm
      PUSH EDI
      PUSH ECX            // A
      PUSH EDX            // Len  CALL UniqueString
      POP  ECX
      LEA  EDI, [EAX]     // EDI <- @S[1]
      POP  EAX
      CLC
    @@L_1:
      TEST BYTE PTR [EDI], $FF
      JNZ  @@L_2
      STOSB
      JMP  @@L_3
    @@L_2:
      INC  EDI
    @@L_3:
      DEC  ECX
      JNZ  @@L_1
      POP  EDI
    end;调用示例:var
      S: string;
    begin
      S := #$31#0#0#0#0#0#$32;
      ReplaceZeroStr(S, Length(S), '^');
      ShowMessage(S);
    end;
      

  13.   

    上面的
    CLC
    请改成
    CLD
      

  14.   

    呵呵,DDGG(叮叮当当)真谢谢你!问题解决了~~~