Delphi基础教程图文版之文件操作 delphi怎么用
liebian365 2024-11-11 14:46 29 浏览 0 评论
无论什么编程语言文件操作这一块的内容都不会缺席,先正式学习之前我们需要先搞清楚几个概念性的东西
- 数据流(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.
C语言风格的API
此套API不像上面的操作,而是全部采用字节的方式进行读取,因为 System.SysUtils 单元的函数很多我做了一下梳理
FileOpen
{函数原型}
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.
译文:重新定位读/写点。
{函数原型}
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.
{函数原型}
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组件进行整合
相关推荐
- go语言也可以做gui,go-fltk让你做出c++级别的桌面应用
-
大家都知道go语言生态并没有什么好的gui开发框架,“能用”的一个手就能数的清,好用的就更是少之又少。今天为大家推荐一个go的gui库go-fltk。它是通过cgo调用了c++的fltk库,性能非常高...
- 旧电脑的首选系统:TinyCore!体积小+精简+速度极快,你敢安装吗
-
这几天老毛桃整理了几个微型Linux发行版,准备分享给大家。要知道可供我们日常使用的Linux发行版有很多,但其中的一些发行版经常会被大家忽视。其实这些微型Linux发行版是一种非常强大的创新:在一台...
- codeblocks和VS2019下的fltk使用中文
-
在fltk中用中文有点问题。英文是这样。中文就成这个样子了。我查了查资料,说用UTF-8编码就行了。edit->Fileencoding->UTF-8然后保存文件。看下下边的编码指示确...
- FLTK(Fast Light Toolkit)一个轻量级的跨平台Python GUI库
-
FLTK(FastLightToolkit)是一个轻量级的跨平台GUI库,特别适用于开发需要快速、高效且简单界面的应用程序。本文将介绍Python中的FLTK库,包括其特性、应用场景以及如何通过代...
- 中科院开源 RISC-V 处理器“香山”流片,已成功运行 Linux
-
IT之家1月29日消息,去年6月份,中科院大学教授、中科院计算所研究员包云岗,发布了开源高性能RISC-V处理器核心——香山。近日,包云岗在社交平台晒出图片,香山芯片已流片,回片后...
- Linux 5.13内核有望合并对苹果M1处理器支持的初步代码
-
预计Linux5.13将初步支持苹果SiliconM1处理器,不过完整的支持工作可能还需要几年时间才能完全完成。虽然Linux已经可以在苹果SiliconM1上运行,但这需要通过一系列的补丁才能...
- Ubuntu系统下COM口测试教程(ubuntu port)
-
1、在待测试的板上下载minicom,下载minicom有两种方法:方法一:在Ubuntu软件中心里面搜索下载方法二:按“Ctrl+Alt+T”打开终端,打开终端后输入“sudosu”回车;在下...
- 湖北嵌入式软件工程师培训怎么选,让自己脱颖而出
-
很多年轻人毕业即失业、面试总是不如意、薪酬不满意、在家躺平。“就业难”该如何应对,参加培训是否能改变自己的职业走向,在湖北,有哪些嵌入式软件工程师培训怎么选值得推荐?粤嵌科技在嵌入式培训领域有十几年经...
- 新阁上位机开发---10年工程师的Modbus总结
-
前言我算了一下,今年是我跟Modbus相识的第10年,从最开始的简单应用到协议了解,从协议开发到协议讲解,这个陪伴了10年的协议,它一直没变,变的只是我对它的理解和认识。我一直认为Modbus协议的存...
- 创建你的第一个可运行的嵌入式Linux系统-5
-
@ZHangZMo在MicrochipBuildroot中配置QT5选择Graphic配置文件增加QT5的配置修改根文件系统支持QT5修改output/target/etc/profile配置文件...
- 如何在Linux下给zigbee CC2530实现上位机
-
0、前言网友提问如下:粉丝提问项目框架汇总下这个网友的问题,其实就是实现一个网关程序,内容分为几块:下位机,通过串口与上位机相连;下位机要能够接收上位机下发的命令,并解析这些命令;下位机能够根据这些命...
- Python实现串口助手 - 03串口功能实现
-
串口调试助手是最核心的当然是串口数据收发与显示的功能,pzh-py-com借助的是pySerial库实现串口收发功能,今天痞子衡为大家介绍pySerial是如何在pzh-py-com发挥功能的。一、...
- 为什么选择UART(串口)作为调试接口,而不是I2C、SPI等其他接口
-
UART(通用异步收发传输器)通常被选作调试接口有以下几个原因:简单性:协议简单:UART的协议非常简单,只需设置波特率、数据位、停止位和校验位就可以进行通信。相比之下,I2C和SPI需要处理更多的通...
- 同一个类,不同代码,Qt 串口类QSerialPort 与各种外设通讯处理
-
串口通讯在各种外设通讯中是常见接口,因为各种嵌入式CPU中串口标配,工业控制中如果不够还通过各种串口芯片进行扩展。比如spi接口的W25Q128FV.对于软件而言,因为驱动接口固定,软件也相对好写,因...
- 嵌入式linux为什么可以通过PC上的串口去执行命令?
-
1、uboot(负责初始化基本硬bai件,如串口,网卡,usb口等,然du后引导系统zhi运行)2、linux系统(真正的操作系统)3、你的应用程序(基于操作系统的软件应用)当你开发板上电时,u...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- go语言也可以做gui,go-fltk让你做出c++级别的桌面应用
- 旧电脑的首选系统:TinyCore!体积小+精简+速度极快,你敢安装吗
- codeblocks和VS2019下的fltk使用中文
- FLTK(Fast Light Toolkit)一个轻量级的跨平台Python GUI库
- 中科院开源 RISC-V 处理器“香山”流片,已成功运行 Linux
- Linux 5.13内核有望合并对苹果M1处理器支持的初步代码
- Ubuntu系统下COM口测试教程(ubuntu port)
- 湖北嵌入式软件工程师培训怎么选,让自己脱颖而出
- 新阁上位机开发---10年工程师的Modbus总结
- 创建你的第一个可运行的嵌入式Linux系统-5
- 标签列表
-
- wireshark怎么抓包 (75)
- qt sleep (64)
- cs1.6指令代码大全 (55)
- factory-method (60)
- sqlite3_bind_blob (52)
- hibernate update (63)
- c++ base64 (70)
- nc 命令 (52)
- wm_close (51)
- epollin (51)
- sqlca.sqlcode (57)
- lua ipairs (60)
- tv_usec (64)
- 命令行进入文件夹 (53)
- postgresql array (57)
- statfs函数 (57)
- .project文件 (54)
- lua require (56)
- for_each (67)
- c#工厂模式 (57)
- wxsqlite3 (66)
- dmesg -c (58)
- fopen参数 (53)
- tar -zxvf -c (55)
- 速递查询 (52)