欢迎大家来到IT世界,在知识的湖畔探索吧!
欢迎大家来到IT世界,在知识的湖畔探索吧!
无论什么编程语言文件操作这一块的内容都不会缺席,先正式学习之前我们需要先搞清楚几个概念性的东西
- 数据流(Data Stream):数据在数据源和程序(内存)之间传递的过程
- 输入流(Input Stream):数据从数据源到程序(内存)的过程
- 输出流(Output Stream):从程序(内存)到数据源的过程
其实Delphi针对文件操作这块的内容提供了 3 套 API 的支持,
- 对win32API封装的一套(System)
- 类似于C语言风格的API(System.SysUtils)
- 新的 API(System.Classes),貌似是在 FireMonkey 支持多平台以后才出现的(没有官网证据)
在网络上查询的过程中大部分 Delphi 文件操作这块的实现都是利用的 System.SysUtils和 System 单元内的函数
IO的分类
根据数据的流向分为:输入流和输出流,根据数据的类型分为:字节流和字符流。
所以这样就产生了字节、字符输入流和字节、字符输出流
Delphi 支持三种文件类型: 文本文件、记录文件、无类型文件(记录类型和无类型文件都可以看作是字节流)。
Win32API
其实这部分内容我是取自 万一老师的博客,自己稍加整理之后得来的
文本文件是以行为单位进行读、写的。由于每一行的长度不一定相同,不能计算出给定行在文件中的确切位置,因而只能顺序地读写。
-文本文件只能单独为读或写而打开,在一个打开的文本文件上同时进行读、写操作是不允许的。
文本文件的打开需要 3 个步骤:
- 文件变量与文件名关联:AssignFile(VarTxt, FileName),FileName 如果省略路径将默认当前目录。
- 初始化读写。
(1) Reset: 只读打开, 指针移到文件头;
(2) Rewrite: 创建新文件并打开, 只写;
(3) Append: 从尾部追加, 指针当然在文件尾。
- 释放读写文件:这一步千万不能忘记
案例代码
以下是我整理的代码,在DelphiXE10.4.2测试通过,理论上这种玩法通杀所有版本
program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; type { 待读写的结构体 } TPersonRec = packed record name: string[12]; age: Integer; birthday: string[24]; end; { 复制文件,也就是最后一种操作类型块数据 } procedure FileCopy(const FileFrom, FileTo: string); var FromF, ToF: file; NumRead, NumWritten: Integer; Buffer: array [1 .. 2048] of Byte; begin { 关联文件 } AssignFile(FromF, FileFrom); { 读 } Reset(FromF, 1); { 关联文件 } AssignFile(ToF, FileTo); { 写 } Rewrite(ToF, 1); { 完成边读边写,即复制的动作 } repeat BlockRead(FromF, Buffer, SizeOf(Buffer), NumRead); BlockWrite(ToF, Buffer, NumRead, NumWritten); until (NumRead = 0) or (NumWritten <> NumRead); { 释放两个文件资源 } CloseFile(FromF); CloseFile(ToF); end; // 结构体读写 procedure ReadRecord(); var { 文件对象或者称为文件句柄,标注文件的类型 } DataFile: file of TPersonRec; PersonRec: TPersonRec; begin AssignFile(DataFile, 'E:\demo1.txt'); { 读取方式 } Reset(DataFile); { 执行读取 } while not Eof(DataFile) do begin Read(DataFile, PersonRec); Writeln(PersonRec.name); Writeln(IntToStr(PersonRec.age)); Writeln(PersonRec.birthday); end; { 关闭,释放资源 } CloseFile(DataFile); end; procedure WriteRecord(); var { 文件对象或者称为文件句柄,标注文件的类型 } DataFile: file of TPersonRec; PersonRec: TPersonRec; begin { 创建结构体数据 } PersonRec.name := '李四'; PersonRec.age := 81; PersonRec.birthday := '1927-11-11'; AssignFile(DataFile, 'E:\demo1.txt'); { 覆盖写入 } Rewrite(DataFile); { 执行写入 } Write(DataFile, PersonRec); { 关闭,释放资源 } CloseFile(DataFile); end; // 文本读写* procedure ReadText(); var { 文件对象或者称为文件句柄,标注文件的类型 } TextFile: Text; Content: string; begin AssignFile(TextFile, 'E:\demo1.txt'); { 只读打开 } Reset(TextFile); { Eof确定与句柄关联的文件是否已达到文件结束。 } while not Eof(TextFile) do begin { 读取 } Readln(TextFile, Content); { 显示 } Writeln(Content); end; { 关闭,释放资源 } CloseFile(TextFile); end; procedure WriteText(); var { 文件对象或者称为文件句柄,标注文件的类型 } TextFile: Text; Content: string; begin Content := '期待哔哩哔哩粉丝过万'; AssignFile(TextFile, 'E:\demo1.txt'); { 追加,即另外一种写的方式 } // Append(TextFile); { 写入打开 } Rewrite(TextFile); Writeln(TextFile, Content); { 关闭,释放资源 } CloseFile(TextFile); end; begin //ReadRecord(); Readln; end.
欢迎大家来到IT世界,在知识的湖畔探索吧!
C语言风格的API
此套API不像上面的操作,而是全部采用字节的方式进行读取,因为 System.SysUtils 单元的函数很多我做了一下梳理
FileOpen
欢迎大家来到IT世界,在知识的湖畔探索吧!{函数原型} function FileOpen(const FileName: string; Mode: LongWord): THandle;
描述信息
- 使用指定的访问模式打开指定的文件
参数介绍
FileName:基本上不需要介绍就是文件名
Mode:它的取值是以下几种
|
Value |
Meaning |
|
fmOpenRead |
Open the file for reading only. |
|
fmOpenWrite |
Open the file for writing only. Writing to the file completely replaces the current contents. |
|
fmOpenReadWrite |
Open the file to modify the current contents rather than replace them. |
|
fmShareCompat |
Sharing is compatible with the way FCBs are opened. |
|
fmShareExclusive |
Other applications cannot open the file for any reason. |
|
fmShareDenyWrite |
Other applications can open the file for reading, but not for writing. |
|
fmShareDenyRead |
Other applications can open the file for writing, but not for reading. |
|
fmShareDenyNone |
No attempt is made to prevent other applications from reading from or writing to the file. |
我没有做翻译,和前面的套路类似,只是感觉Delphi重新做了封装
FileRead
官方描述:Reads a specified number of bytes from a file.
译文:从文件中读取指定的字节数。
{函数原型} function FileRead(Handle: THandle; var Buffer; Count: LongWord): Integer; function FileRead(Handle: THandle; var Buffer: TBytes; Offset, Count: LongWord): Integer;
为什么有两个,很明显是重载的函数,这个没关系,根据我们自己的情况进行调用即可
参数介绍
Handle:很明显就是前面的文件句柄
Buffer:一个缓冲区指针
Count:读取的长度
有了这个函数感觉就可以开干了
FileSeek
官方描述:Repositions read/write point.
译文:重新定位读/写点。
欢迎大家来到IT世界,在知识的湖畔探索吧!{函数原型} function FileSeek(Handle: THandle; Offset, Origin: Integer): Integer; function FileSeek(Handle: THandle; const Offset: Int64; Origin: Integer): Int64;
参数描述
Handle:文件句柄(或者称为文件指针)
Offset:翻译过来是偏移量
Origin:翻译过来是原点的意思,它有 3 个取值
|
Origin |
Action |
|
0 |
The file pointer is positioned Offset bytes from the beginning of the file. |
|
1 |
The file pointer is positioned Offset bytes from its current position. |
|
2 |
The file pointer is positioned Offset bytes from the end of the file. |
FileWrite
官方描述:Writes the contents of a buffer to the current position in a file.
译文:将缓冲区的内容写入文件中的当前位置。
{函数原型} function FileWrite(Handle: THandle; const Buffer; Count: LongWord): Integer; function FileWrite(Handle: THandle; const Buffer:TBytes; Offset, Count: LongWord): Integer;
参数描述
Handle:文件句柄
Buffer:缓冲区
Count:写入的长度,理论上应该就是缓冲区的长度
Offset:偏移量
FileClose
官方描述:Closes a specified file.
欢迎大家来到IT世界,在知识的湖畔探索吧!{函数原型} procedure FileClose(Handle: THandle);
Handle:文件句柄
案例代码
核心函数就这么几个,案例也不需要我来写,官方提供了案例,我拿过来而已
读数据:
http://docwiki.embarcadero.com/CodeExamples/Sydney/en/FileRead_(Delphi)
写数据:
http://docwiki.embarcadero.com/CodeExamples/Sydney/en/FileToGrid_(Delphi)
新版API
官方文档:
http://docwiki.embarcadero.com/Libraries/Sydney/en/System.IOUtils
这个单元包括三个主要的类:TPath, TDirectory, TFile,基本上都是和文件及文件夹相关
官方文档:
http://docwiki.embarcadero.com/Libraries/Sydney/en/System.Classes
案例代码
program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.Classes, System.IOUtils, System.SysUtils; type { 测试数据 } TPerson = record Name: string; Age: Integer; end; { 写文本数据 } procedure WriteLine(); var StreamWrite: TStreamWriter; begin // 创建TStreamWriter StreamWrite := TStreamWriter.Create('E:\Demo\Person.txt'); // 写入数据 StreamWrite.WriteLine('期待哔哩哔哩粉丝过万'); // 释放资源 FreeAndNil(StreamWrite); end; { 读取文本数据 } procedure ReadLine(); var Reader: TStreamReader; begin // 创建TStreamWriter Reader := TStreamReader.Create('E:\Demo\Person.txt', TEncoding.ANSI); // 读取数据 while not Reader.EndOfStream do begin // 读取内容 Writeln(Reader.ReadLine); end; // 释放资源 FreeAndNil(Reader); end; { 读结构体数据 } procedure ReadRec(); var FileStream: TFileStream; var Person: TPerson; begin try FileStream := TFileStream.Create('E:\Demo\Person.txt', fmOpenRead); // 设置文件指针的位置 FileStream.Position := 0; // 遍历流中的数据(字节) while FileStream.Position < FileStream.Size do begin FileStream.Read(Person, sizeof(Person)); Writeln(Person.Name + ',' + Person.Age.ToString); end; finally FreeAndNil(FileStream); end; end; { 写结构体数据 } procedure WriteRec(); var FileStream: TFileStream; var Person: TPerson; begin try FileStream := TFileStream.Create('E:\Demo\Person.txt', fmCreate); // 构造结构体数据 Person.Name := '萧蔷'; Person.Age := 20; // 写出数据 FileStream.Write(Person, sizeof(Person)); finally FreeAndNil(FileStream); end; end; // *读写字节数据 { 文件复制 } procedure FIleCopy(); var WriteFileStream, ReadFileStream: TFileStream; begin try // 创建对象 ReadFileStream := TFileStream.Create('D:\常用软件下载.txt', fmOpenRead); WriteFileStream := TFileStream.Create('E:\Demo\a.txt', fmCreate); // 设置读取的位置 ReadFileStream.Position := 0; WriteFileStream.CopyFrom(ReadFileStream, ReadFileStream.Size); finally FreeAndNil(ReadFileStream); FreeAndNil(WriteFileStream); end; end; { 写数据 } procedure WriteStringByByte(); var FileStream: TFileStream; var Str: string; var StrByte: TBytes; begin // 字符串的长度、字符编码 Unicode、utf-8、gbk Str := '期待B站粉丝破万'; try FileStream := TFileStream.Create('D:\常用软件下载.txt', fmCreate); // 将string转换为指定编码的字节数组 StrByte := TEncoding.UTF8.GetBytes(Str); FileStream.WriteBuffer(StrByte, Length(StrByte)); finally FreeAndNil(FileStream); end; end; { 读数据 } procedure ReadUtf8String(); var FileStream: TFileStream; var Str: UTF8String; begin FileStream := TFileStream.Create('D:\常用软件下载.txt', fmOpenRead); FileStream.Position := 0; // 缓冲区大小 SetLength(Str, FileStream.Size); // 读取数据:解除指针引用,获取变量中的值 FileStream.Read(PChar(Str)^, FileStream.Size); Writeln(Str); FreeAndNil(FileStream); end; begin ReadUtf8String(); Readln; end.
PS:Delphi文件操作这块乱七八糟的的,网络上的代码也参差不齐,很容易陷入死胡同,以上内容仅仅是常规操作并没有和VCL组件进行整合
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/109513.html