请问copy一个大字符串是不是很花时间 ( 积分: 30 )

  • 主题发起人 主题发起人 我爱PASCAL
  • 开始时间 开始时间

我爱PASCAL

Unregistered / Unconfirmed
GUEST, unregistred user!
一个几十上百兆的string
str2:=copy(str, 5, length(str))
这样又要分配一个内存空间,占内存不说,还费时。
 
试一下保存成文件操作它
 
一个及时上百M的string为什么不用流来做?在内存中整体拷贝肯定受不了的。
 
FileStream := TMemoryStream.Create;
try
FileStream.LoadFromFile(FileName);
FileStream.position:= 0;
SetLength(FileStr, FileStream.size);
FileStream.ReadBuffer(FileStr[1], FileStream.size);
finally
FileStream.Free;
end;
这样的话,还是要从流中拷到变量filestr中,
有没有字符串直接映射到流的方法。
 
PChar(FileStream.Memory)
 
FileStr := PChar(FileStream.Memory);
SetLength(FileStr, FileStream.size);
这样,得到的前几十个字符正确,后面就是乱码了。
 
var
pc: PChar;
begin
pc := @str1[30]
//pc 指向str1的第30个字符到str1的尾,pc 与 str1 共享内存,
... //pc没分配内存,所以不释放
 
楼上大哥是什么意思,没听懂
 
上百兆的str直接复制一个一模一样的又有什么用.
要快的就只能用virutalalloc和copymemory了。
 
这么大串,应该用流+分块读写,不要一次全部读入到内存.
 
没用的.
setlength字符串会重新分配,并尽量复制原来的内容.
 
你的意图
1:现有一字符串str1,须要另一个变量共享str1变量的值
此情况使用PChar比较方便

2:现有一字符串str1,须要从str1中拷贝一段赋与另一变量另做它用,新变量与str1不相关,两上变量完全独立
此情况只能使用拷贝了(对于很大的数据量,不管是用Copy、流、move,都差不多,即使优化也快不子多少),别无它法。
 
需求不对, 无讨论价值
 
tseug 说得没错。您可以 FileStr := PChar(FileStream.Memory)


不过您不需要再 SetLength 了,直接访问 FileStr 就可以了,只要保证 I < FileStream.Size。

另外,如果文件里的字符含有 #0,那直接访问 FileStr 就不能得到正确的内容,所以后面的用法就需要注意,最好用指针移动来访问其中的内容。
 
过程是这样的:
有一些大小不一的文件,文件类型不限。
我要把它读入后,到一字符串中,比如FileStr
在处理这个FileStr,比如用过程
HandleStr(FileStr);
处理完后,我又把它写回文件。
于是我用的是TMemoryStream
FileStream := TMemoryStream.Create;
try
FileStream.LoadFromFile(FileName);
FileStream.position:= 0;
SetLength(FileStr, FileStream.size);
FileStream.ReadBuffer(FileStr[1], FileStream.size);
HandleStr(FileStr);//我的处理
finally
FileStream.Free;
end;
最后再用SaveToFile保存回去。
我在运行时在观查了它的内存情况;
比如处理一百兆的文件,内存使用就增加一百兆。
不知道各位大哥有没有什么更优化的办法。
 
为什么不用文件映射对象呢,windows核心编程里提到好像这种方法对大文件特别有效
不过我还没有试过
 
文件映射对象相当有效

FileHandle:=CreateFile(PChar(FileName),
GENERIC_READ,0,Nil,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
If FileHandle<>INVALID_HANDLE_VALUE Then
begin
try
MapHandle:=CreateFileMapping(FileHandle,
Nil,PAGE_READONLY,0,0,Nil);
If MapHandle<>NULL Then
Begin
try
Log:='成功打开文件'#$0D#$0A;
Addr:=MapViewOfFile(MapHandle,FILE_MAP_READ,0,0,0);
If Addr<>Nil Then
begin
try
Log:=Log+'成功建立映射对象'#$0D#$0A;
DoWork(Addr,GetFileSize(FileHandle,Nil));
finally
If UnmapViewOfFile(Addr) Then
Log:=Log+'成功撤消文件映射'#$0D#$0A;
end;
end;
finally
CloseHandle(MapHandle);
end;
End;
finally
CloseHandle(FileHandle);
end;
end;
 
用指针啊,你说说你的最终操作,看看能不能用指针。
 
都不能解决实质的问题
比如要在一个1G的文件前加一个头,比如一个字节。怎么办。文件映射可能也不行。
好比在一个大石头下垫入一张纸,怎样不移动大石头的情况下垫入这张纸。
 
也不是不行,只是要用到操作系统的文件结构,实际是对操作系统文件信息的修改.以fat文件为例: 首先在fat文件分区表找出一块空闲块,写入内容,将原文件头索引指向空闲块,在空闲块链接指针指向原文件头索引
 
后退
顶部