我已经尝试将文件读取到TFileStream中,但是那是我被卡住的地方,文件已插入TFileStream中,但是我无法读取文件的字节,我已经有一段时间没有编程了,请帮助我。
我也尝试将其读入普通文件
var
myFile : File;
byteArray : array of byte;
oneByte : byte;
i, count : Integer;
begin
// Try to open the Test.byt file for writing to
AssignFile(myFile, 'C:\Users\theunie\Desktop\Toets\Test2.txt');
// Reopen the file for reading only
FileMode := fmOpenRead;
Reset(myFile, 1); // Now we define one record as 1 byte
// Display the file contents
// Start with a read of the first 6 bytes. 'count' is set to the
// actual number read
ShowMessage('Reading first set of bytes :');
setlength(ByteArray,sizeof(myfile));
BlockRead(myFile, byteArray, sizeof(myFile), count);
// Display the byte values read
for i := 0 to count do
ShowMessage(IntToStr(byteArray[i]));
// Now read one byte at a time to the end of the file
ShowMessage('Reading remaining bytes :');
while not Eof(myFile) do
begin
BlockRead(myFile, oneByte, 1); // Read and display one byte at a time
ShowMessage(IntToStr(oneByte));
end;
Freeandnil(byteArray);
// Close the file for the last time
CloseFile(myFile);
end;
以及这个
procedure TForm1.Button1Click(Sender: TObject);
var
tf : TFileStream; //My Filestream
ar : array of byte;//The dynamic array I want to read it into
k : integer;//count
s : string;//I want to display this at the end
begin
k := 0;
tf := TFileStream.Create('C:\Users\Theunie\Desktop\Test2.txt',fmOpenReadwrite);
try
inc(k);
SetLength(ar,k);
ar[k-1] := tf.Read(ar[k-1],tf.size);
finally
s := inttostr(ar[0]) +';';
for k := 1 to length(ar) do
begin
s := s + ';' + IntToStr(ar[k]);
end;
FreeAndNil(ar);
end;
RichEdit1.Lines.Add(s);
end;
最佳答案
文件大吗?它可以一次放入RAM吗?
基本上,有两个简单的选项可以从文件中创建DynArray,但仅建议将它们用于中小型文件。
1:http://www.freepascal.org/docs-html/rtl/classes/tbytesstream.html
var BS: TBytesStream; b: byte; L, i: integer;
begin
BS := TBytesStream.Create;
try
BS.LoadFromFile('c:\boot.ini');
L := High(BS.Bytes);
for i := 0 to L do begin
b := BS.Bytes[i];
ShowMessage( IntToStr( b ) );
end;
finally
BS.Destroy;
end;
end;
2:使用IOUtils类
http://docwiki.embarcadero.com/Libraries/XE8/en/System.IOUtils.TFile.ReadAllBytes
http://www.malcolmgroves.com/blog/?p=447
http://www.programdevelop.com/4641326/
Why do the System.IOUtils functions and TStreamReader use fmShareCompat?
等等
var BS: TBytes; b: byte; L, i: integer;
begin
BS := TFile.ReadAllBytes('c:\boot.ini');
L := High(BS);
for i := 0 to L do begin
b := BS[i];
ShowMessage( IntToStr( b ) );
end;
end;
相反,要将数组的内容保存到文件中,可以使用How to convert TBytes to Binary File? (using MemoryStream)之类的东西
关于您的尝试。
http://wiki.freepascal.org/File_Handling_In_Pascal
如上所述,
SizeOf
与文件无关,即File
变量类型的内存大小。如果要坚持使用旧的TurboPascal API,则必须使用FileSize
函数立即设置大小。对于小文件,它可以正常工作,对于大文件,“立即将所有内容立即读取到内存,然后进行处理”的方法是错误的。inc(k); SetLength(ar,k);
-在+1循环中-这是一个非常糟糕的主意,它意味着堆碎片以及复制和重新复制以及重新复制遍历数据缓冲区一次又一次。这是Length*Length/2
扩展,也可能会严重破坏堆内存结构(有关heap fragmentation
的Google)。如果可以-您需要先检查
FileSize
并将数组设置为FreeAndNil(byteArray);
-完全错误。数组不是对象。您不能对它们使用Destroy / Free / FreeAndNil。那么如何清洁dynarray呢?好吧,您可能什么也不做,因为dynarrays是自动引用计数类型之一,例如字符串和接口等。只要过程退出,Delphi就会自动从局部变量中释放内存。
但是,如果要在过程中间清理dynarray,则可以通过
SetLength( MyDynArray, 0 )
或快捷方式MyDynArray := nil
来完成。错误使用
BlockRead(myFile, byteArray, sizeof(myFile), count)
导致SizeOf
错误。但是它还有另一个缺点:ByteArray
变量基本上是一个指针,因此它只有4个(四个!)字节(在Win64代码中为8个字节),因此您只需覆盖所有调用堆栈。您确实应该更好地使用现代类型安全的API。但是,如果您要使用旧的不安全的低级API,则必须非常清楚不同类型变量的低级实现。基本上,您不想将文件内容读入指向缓冲区的指针中,而是读入指向的缓冲区中,因此它应类似于BlockRead(myFile, byteArray[0], MyFileAndArraySize, count)
。然后,如果只读取了文件的一部分-count < MyFileAndArraySize
-您将选择BlockRead(myFile, byteArray[count], MyFileAndArraySize - count, count1)
,然后是BlockRead(myFile, byteArray[count+count1], MyFileAndArraySize - count - count1, count2)
,依此类推。即使您了解低级类型中的字节是如何运行的,也很乏味...
ar[k-1] := tf.Read(ar[k-1],tf.size);
-绝对是可悲的。检查http://www.freepascal.org/docs-html/rtl/classes/tstream.read.html-结果是实际读取了多少个字节。因此,您不会以“一次尝试读取多少字节?”的感觉来填充文件内容。代替。您最好改用tf.ReadBuffer
过程。但是,如果您想遍历
tf.Read
部分,它应该类似于k := 0;
SetLength(ar, tf.Size);
while k < tf.Size do begin
k := k + tf.Read( ar[k], tfSize - k);
end;
但是同样,您可以使用更简单的工具来处理现代Delphi中的小文件
您代码中的另一个问题是
s := inttostr(ar[0]) +';';
for k := 1 to length(ar) do
begin
s := s + ';' + IntToStr(ar[k]);
end;
这是所谓的“一次性错误”。
尽管出于歇斯底里的原因,字符串的索引从1到
Length(s)
,并且通常不包含第0个元素,但dynarrays却没有。动态数组从
0 = Low(ArrayVarName)
索引到High(ArrayVarName) = Length(ArrayVarName) - 1
。因此,您的循环尝试读取数组末尾(数组本身之外)的内存。另一个错误是您以两个分号开头,例如“ 10 ;; 20; 30; 40 .....”
当您感到疲倦或注意力不集中时,通常会发生这种情况。因此,您最好完全避免索引数组。
下面是从Delphi XE2将动态数组转换为字符串的工作代码
procedure TForm1.Button1Click(Sender: TObject);
var DynamicArray: TBytes;
SB: TStringBuilder; iSL: IJclStringList;
s1,s2: string; b: byte;
begin
DynamicArray := TBytes.Create( 10, 20, 30, 40, 50 );
SB := TStringBuilder.Create;
try
for b in DynamicArray do begin
if SB.Length > 0 then
SB.Append( ';' );
SB.Append( b );
end;
s1 := SB.ToString;
finally
SB.Destroy; // you must do it in Delphi for Windows
end;
iSL := JclStringList();
for b in DynamicArray do
iSL.Add( IntToStr( b ) );
s2 := iSL.Join( ';' );
iSL := nil; // you may skip it, Delphi would do on exit from procedure
ShowMessage( 'Dynamic array of bytes to string'
+ ^M^J' with Delphi RTL: ' + s1
+ ^M^J' with J.E.D.I. Code Library: ' + s2);
end;
有关动态数组的更多信息:
https://delphihaven.wordpress.com/2009/12/09/dynamic-arrays-as-reference-types/
http://blog.marcocantu.com/blog/2014_september_dynamic_arrays_delphixe7.html
关于delphi - 需要一次将任何扩展名为XE5的一个字节的文件读入动态数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30485418/