该read函数说明:read(Var BUF;Size:int64);
BUF代表缓冲区(始址??)SIZE为从某文件流中读取数据到缓冲区的字节数。
我有一STRING变量:S:setlength(s,20);
下为出错代码:
tfileStream.create(filename).read(s,10):编译能通过,但运行到该句后发生ACCESSViolation异常。
修改后:tfileStream.create(filename).read(pointer(s)^,10);运行正常??!!
请各位大侠不吝指教,谢谢了!!

解决方案 »

  1.   

    function Read(var Buffer; Count: Longint): Longint; override;property Buffer: PChar;因为你的变量s是string类型,需要转换为CHAR类型才可以用
      

  2.   

    tfileStream.create(filename).read(s[1],10);
      

  3.   

    谢谢zsjzwj的分析。他找到了问题所在,只是不详细:string默认是AnsiString,一个4字节的指针。PCHAR是一个NULL-TERMINATE类型(以#0结尾)的字符串。(应该和AnsiString一样是一个4字节的指针?)同样是指针,为何有区别?
       感觉alexanda2000更进了一步,s[1]为字符串第一字符。但BUF一般是指针啊?我就是这个不理解?!
      

  4.   

    string实际上就是指针,也是以#0结尾,只是它指向的不是第一个字符。S[1]才是它的字符开始的地方。
      

  5.   

    tfileStream.create(filename).read(s,10)实际上将流的数据写入了字符串用来存储其它相关信息的地方,所以就会出错了。
      

  6.   

    另外我用“S^”来指定第一个字符,不用s[1],编译都有问题.为什么??(我以前的C语法在Delphi老是不管用!)类似C中:string S;
                         printf(%c,*S)与printf(%c,S[0])一样的吧?
      

  7.   

    看一下read定义:
    function Read(var Buffer; Count: Longint): Longint; override
    BUffer显然是一个指针啊!
    S[1]是个字符。这能对吗??
      

  8.   

    S[1]可以用,但最好用PChar(s)来取得首地址,切记要先使用SetLength给字符串分配空间,否则还是有可能访问非法地址。另外,Delphi的语法与C不一样,C当中数组和指针是一回事,但在Delphi中不是,更何况String类型并非数组。
      

  9.   

    注意pointer(s)^应该也表示S中第一个字符?或是其他?
    另外tfileStream.create(filename).read(s[1],10);是不是能运行正常,我还没试过呢,明天给答案:-)
      

  10.   

    对于你的要求,最好自定义一个字符数组作为Buf:
    var
      Buf: array[0..1023] of char;
      

  11.   

    S[1],s[1],s[1]...........
    to  lyre:你的方法是对的,数组名是指针。那字符串名到底是不是指针??
    “C当中数组和指针是一回事,但在Delphi中不是”说得具体点~~ 
      

  12.   

    Delphi是强类型的语言,不像C中指针和数组可以通用,虽然实际上数组名作为一个变量来说,确实有一个对应的内存地址,而且你把它强制转换为指针后,访问的内容也是正确的。
    Delphi中的字符串实际上是以前Pascal短字符串与C的以0结尾的字符串的一种综合体,也就是说,最前面有几个字节保存的是字符串的长度,然后是实际内容,最后又有一个结尾的0。
      

  13.   

    lyre说得没错,对于第二段内容我也了解。(第一段精彩!)
    回到问题:
    那s[1]是不是指针?
    BUF指得是一个指针变量?
    如果BUF是指针,那Pointer(S)^代表的是一个字符还是指针?[参数类型匹配吗?]
    S^与Pointer(S)^的区别?(STRING指针与无类型指针我知道(都4字节),但不能替换使用,否则上面程序异常。难道这就是所谓“强类型”?)
      

  14.   

    S[1]不是指针,而是指字符串的第1个字符。你注意read的定义:
    read(Var BUF;Size:int64);
    其中的Buf是一个无类型参量,这种情况下调用时不限参数类型。另外Buf是作为var定义的,传递参数时是将参数的地址传进去的。(实际上无类型参数也只能用var来定义。)C语言这种情况下需要&符来取址,Delphi不需要。
    read(s[1], ..);    ==>传入S[1]的地址。因为String类型的第一个字符下标从1开始,所以S[1]的地址也正是字符串正文开始的地址;S虽然实际上是个指针,但这是对Delphi而言的,在引用的时候Delphi会循着S指明的地址依次找到字符串长度、内容、结尾的0等;对用户而言它是一个语言内建的数据类型而不是指针,所以S^的写法是错误的。
    如果你把S强行转化为指针,将Pointer(S)^作为参数传给Read的时候,它实际指向字符串开头的字符串长度所在位置,你往这里写东西,当然就破坏了字符串的结构了;
      

  15.   

    lyre(大头鬼)已经解释得很清楚了,read(Var BUF;Size:int64);中的buf是变参,read方法接收到的已经是buf的地址了,因此buf不需要传入指针变量。如果你真的传入一个指针,这个方法接收到的就是指针自身地址了,反而会出错。因此用s[1]作为buf的话,这个方法接收到的是s[1]的地址。在Delphi中,数组不是指针,声明一个arr:array[0..12] of char,你看一下SizeOf(arr)就知道了。PS:我觉得将Pointer(S)^作为参数传给read是可以的,因为Pointer(S)^表示了“S正文的内容”,它的地址应该和s[1]是一样的。
      

  16.   

    问题已经解决了。谢谢各位兄弟!!
    分数将对半分给 lyre和 alexanda2000
    另外 alexanda2000最后的回复是正确的,我已验证。原因我琢磨应该如下:
    S作为一个“指针”来说,是一个指向STRING第一字符的指针,而不是指向长度值。
    S作为一个字符串来说,S^不能用,即Delphi限制用户只能从s+1开始。
    Pointer(S)^==s[1]
      

  17.   

    >>>S作为一个“指针”来说,是一个指向STRING第一字符的指针,而不是指向长度值。错了,如果它真的指向第一个字符,就不用s[1]这么麻烦了。
    《Delphi5 开发人员指南》中对字符串结构有比较详细的介绍。