D string中有空字符$0$0 nodepad++打开显示为NUL ,不是空格,造成TStringList处理读取中断(估计认为是终止符合)

2020-11月份 碰到 和下方网友问题。

 

(9条消息) 使用TStringList读取文件只读取到一半是怎么回事-CSDN论坛
https://bbs.csdn.net/topics/390138917

读取某些TXT时,只读了前一半,后面的没了,如果我用记事本打开TXT,什么都不做,直接文件-》保存,就可以了,我用16进制打开看到的是一样的呀,有知道这是怎么回事吗?并且没保存前怎么读全呢?
2012-07-18 09:56:58 楼主
比较下读取完全的和不完全的文件之间的区别,大小或者带有特殊符号。
2012-07-18 10:50:24 #1得分 2

有可能与TXT文件的换行格式有关,可以分别试一下读DOS格式、UNIX格式和MAC格式的情况,然后再试一下混合格式
如没问题的话在检查一下有没有特殊字符
找到原因,只在之前中间有\0,用记事本打开在保存,这些\0就没了,有什么办法替换掉这些\0吗
文本文件里没结束就出现了结束符\0,这个要怎么样替换掉呢?
hyz_cs
你这个文件不是文本文件吧,要不然里面怎么会有\0呢,或者编码不对?
_fastcall
文件后半部分还没有保存
LWLIFE
这个是别人导出的文本文件,里面有我需要的描述信息,用十六进制查看的时候在中间地方就是有\0的存在,所以我用TStringList加载的时候只加载了前半部分,有什么办法解决吗?
sczyq
先读取到 TMemoryStream 流,逐个字节判断是否 0x00 就改为 0x20 (空格),
再 TStringList-〉LoadFromStream 装入这个流。
LWLIFE
谢谢楼上的回复,我现在就是这么做的,循环流判断的时候怎么直接替换流里的内容呢?比如流长度20,10的位置就是\0
我现在的做法是,循环判断不是\0就加到另一个字符串,然后最后显示另一个字符串。有什么办法直接修改流里的内容呢?
Blank
打开文件,直接都读到内存中,然后进行替换,把'\0'都替换成空格,然后在用TStringList去读进行了,或者不用TStringList,直接处理也行
2012-07-18 18:41:16
View文章原文 Code

//====

本人的文本中有 存入是$0$0 nodepad++ 打开后是 NUL 是空字符 但不是空格。TStringList处理的时候认为是结束字符,不往下读取了。

 

 本人原来用http请求回来时 内存流中  TMemoryStream 通过TstringStream 转换为UTF8可以看到汉字,

Stream.DataString方法转成string,#0 替换为空格#32 完成目标。
测试例子:
procedure TForm9.btn3Click(Sender: TObject);
var
  sPostUrl : string;
  postStream,outStream : TMemoryStream;
  resstring : string;
  B:array of Char;
  I : Integer;
  P:PChar;
  strs: TStringList;
  Stream : TStringStream;
begin
  sPostUrl := 'http://*****/alarmqueries';
  idhtp1.Request.ContentType := 'application/x-www-form-urlencoded'; // 定义发送mime类型
  postStream := TStringStream.Create('param={"end":"2020-10-22 23:59:59","commno":["14765145811"],"begin":"2020-10-22 00:00:00"}');  // 发送内容
  outStream := TMemoryStream.Create;
  idhtp1.Post(sPostUrl,postStream,outStream);
  outStream.Position := 0;
  Stream := TStringStream.Create('',TEncoding.UTF8);
  Stream.LoadFromStream(outStream);
  resstring :=Stream.DataString;
  for i :=0 to Length(resstring) - 1 do
  begin
    if resstring[i] = #0 then
    begin
      resstring[i] := #32
    end;
  end;
  strs := TStringList.Create();
  strs.Text:=resstring;
  mmo1.Text :=((resstring));// outStream.DataString;
  showmessage(inttostr(mmo1.Lines.Count));
  showmessage(inttostr(strs.Count));
end;

 项目中:

function TGQHttp<T>.PostEx(url: string; paramList: THttpParams;
  postJson: string): THttpResults<T>;
var
  inStream, outStream: TMemoryStream;
  prm: THttpParam;
  prms: TStringList;
begin
  CheckTask;
  try
    outStream := nil;
    inStream := TMemoryStream.Create;
    prms := TStringList.Create;
    if ((paramList <> nil) and (paramList.Count > 0)) then
    begin
      if (rightstr(url, 1) <> '?') then
        url := url + '?';
      for prm in paramList do
        url := url + prm.ToString();
    end;
    if (UpperCase(LeftStr(url, 4)) <> 'HTTP') then
      url := fRootURL + url;
    OutputDebugString(PWideChar('post:' + url + fJsonParamName + ':' +
      postJson));
    try
      if (postJson <> '') then
        prms.Add(fJsonParamName + '=' + postJson);
      // OutputDebugString(PWideChar('json:' + postJson));
      self.PostTest(url, prms, inStream);
      if self.Response.ContentEncoding = 'gzip' then
      begin

        inStream.Position := 0;
        outStream := TMemoryStream.Create;
        GZDecompressStream(inStream, outStream);
        OutputDebugString(PWideChar('压缩传输:' + inttostr(inStream.Size) + '/' +
          inttostr(outStream.Size)));
        result := THttpResults<T>.Create(true, 'OK', outStream, url,prms.Text);
      end
      else
      begin
        result := THttpResults<T>.Create(true, 'OK', inStream, url,prms.Text);
        OutputDebugString(PWideChar('未压缩'));
      end;

    except
      on ex: Exception do
      begin
        result := THttpResults<T>.Create(false,
          '网络查询失败:请检测网络连接' + ex.Message, nil, url);
      end;
    end;

  finally
    FreeAndNil(paramList);
    FreeAndNil(prms);
    FreeAndNil(inStream);
   if(Assigned(outStream)) then FreeAndNil(outStream);
  end;
end;
View Code

 

constructor THttpResults<T>.Create(aIsSucc: Boolean; msg: string;
stream: TStream; aURL: string; aParamStr: string);
var
  strs: TStringList;
  i: Integer;
  StrStream : TStringStream;
  DataStr:string;
begin
  self.fIsSucc := aIsSucc;
  self.fMsg := msg;
  self.Url := aURL;
  self.fParamStr := aParamStr;
  self.fData := TEntitys<T>.Create;
  strs := TStringList.Create();
  if ((self.fIsSucc) and (stream <> nil)) then
  begin
    try
      stream.Position := 0;

      if PosEx('/alarmqueries', aURL, 1)<1 then
      begin
        strs.LoadFromStream(stream, TEncoding.UTF8);
      end else
      begin
        StrStream := TStringStream.Create('',TEncoding.UTF8);
        StrStream.LoadFromStream(stream);
        DataStr :=StrStream.DataString;
        for i :=0 to Length(DataStr) - 1 do
        begin
          if DataStr[i] = #0 then
          begin
            DataStr[i] := #32
          end;
        end;
        strs.Text:=DataStr;
        FreeAndNil(StrStream);
      end;
      // strs.SaveToFile('c:\debug.txt');
      self.fData.FillByStrings(strs);

    except
      on ex: Exception do
      begin
        self.fIsSucc := False;
        self.fMsg := '发生错误:' + ex.Message + #13 + 'URL' + aURL + #13 + 'Param' +
          aParamStr;
        // strs.SaveToFile('c:\debug.txt');
        // TTask.ShowMsg(self.msg);
      end;
    end;

  end;
  FreeAndNil(strs);
end;

普通的将内存流 转换成TStringList 处理。

如果是有问题的API 将内存流转换成string流 TStringStream,再TStringStream.DataString 将有问题的字符替换掉,再给回TStringList.Text ,这个过程相当于绕个弯处理一下。

 

问题到此处理结束。下方是折腾过程的小曲折。可以忽略不看。

//---一开始本来以为是要在流中处理的,但是技术不精,没有弄懂,下方放点杂乱代码,

这个是以一个个字节判断,不知道什么作用

bom: array[0..1] of byte;
if (stream.Read(bom, sizeof(bom)) = 2) and (bom[0] = $FF) and (bom[1] = $FE) then

 

 

 

procedure TXLSStream.WriteFile(RecId, Length: word; Filename: string);
var
  S: string;
  B: byte;
  Stream: TFileStream;
begin
  Stream := TFileStream.Create(Filename,fmOpenRead);
  try
    WriteHeader(RecId,Length);
    SetLength(S,3);
    while (Length > 0) and (Stream.Read(Pointer(S)^,3) = 3) do begin
      B := 0;
      if AnsiChar(S[1]) in ['0'..'9'] then
        B := (Byte(S[1]) - Byte('0')) shl 4
      else if AnsiChar(S[1]) in ['A'..'F'] then
        B := (Byte(S[1]) - Byte('A') + 10) shl 4;
      if AnsiChar(S[2]) in ['0'..'9'] then
        B := B + (Byte(S[2]) - Byte('0'))
      else if AnsiChar(S[2]) in ['A'..'F'] then
        B := B + (Byte(S[2]) - Byte('A') + 10);
      WByte(B);
      Dec(Length);
    end;
  finally
    Stream.Free;
  end;
end;

 

//==== 这里面的流转换成string ,没试

封装了三个对TMemoryStream操作的函数,大牛莫笑 - 似水@流年 - 博客园
https://www.cnblogs.com/wuxi15/p/5134863.html

posted @ 2020-11-24 14:47  海蓝7  阅读(217)  评论(0编辑  收藏  举报