如何在 Delphi 中读取 ISO 9660?
Ho to read ISO 9660 in Delphi?
我目前正在处理一个项目,需要知道刻录 DVD 的时间(刻录 DVD 的日期)。据我搜索和查找,发现所有此类数据都遵循 ISO 9660 格式,但我找不到如何访问或读取它,也尝试了一些相关的组件包和库,但是 none他们按照我的预期和需要工作。
也发现了这个 link:How to find out when a disc (DVD) has been written/burned? 但我找不到在 Delphi 中使用它们的方法。
它是如何工作的?
在 link 之后对此答案:How to find out when a disc (DVD) has been written/burned? 给出了在磁盘上读取日期和时间信息的位置:
读取 16 个字符加上从位置 33582 开始的一个附加字节,得出 DVD 创建时间为:
YYYYMMDDHHMMSSCCO
其中 CC 是厘秒,O 是以 15 分钟为间隔与 GMT 的偏移量,存储为 8 位整数(二进制补码表示)。
可以使用以下代码来阅读(另见How to read raw block from an USB storage device with Delphi?):
function GetDVDCreationDate: String;
// Sector size is 2048 on ISO9660 optical data discs
const
sector_size = 2048;
rdPos = (33582 DIV sector_size); // 33582
rdOfs = (33582 MOD sector_size) - 1;
var
RawMBR : array [0..sector_size-1] of byte;
btsIO : DWORD;
hDevice : THandle;
i : Integer;
GMTofs : ShortInt;
begin
Result := '';
hDevice := CreateFile('\.\E:', GENERIC_READ, // Select drive
FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if hDevice <> INVALID_HANDLE_VALUE then
begin
SetFilePointer(hDevice,sector_size * rdPos,nil,FILE_BEGIN);
ReadFile(hDevice, RawMBR[0], sector_size, btsIO, nil);
if (btsIO = sector_size) then begin
for i := 0 to 15 do begin
Result := Result + AnsiChar(RawMBR[rdOfs+i]);
end;
GMTofs := ShortInt(RawMBR[rdOfs+16]); // Handle GMT offset if important
end;
CloseHandle(hDevice);
end;
end;
请注意,从光盘读取原始数据必须从扇区大小的偶数位置开始。对于 ISO 9660 个磁盘,扇区大小为 2048。
感谢@LU RD 的回答,这里是他的代码,稍作修改:
function GetDVDCreationDate(sectorSize:integer): String;
// Sector size is 2048 on ISO9660 optical data discs
var
RawMBR : array [0..2047] of byte;
btsIO : DWORD;
hDevice : THandle;
i : Integer;
GMTofs : ShortInt;
rdPos, rdOfs: integer;
begin
rdPos := (33582 DIV sectorSize); // 33582
rdOfs := (33582 MOD sectorSize) - 1;
hDevice := CreateFile('\.\H:', GENERIC_READ, // Select drive
FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if hDevice <> INVALID_HANDLE_VALUE then
begin
SetFilePointer(hDevice,sectorSize * rdPos,nil,FILE_BEGIN);
ReadFile(hDevice, RawMBR[0], sectorSize, btsIO, nil);
for i := 0 to 15 do begin
Result := Result + AnsiChar(RawMBR[rdOfs+i]);
end;
GMTofs := ShortInt(RawMBR[rdOfs+16]); // Handle GMT offset if important
CloseHandle(hDevice);
end;
end;
//------------------------------------------------------------------------------
procedure Tfrm_main.btn_creationReadClick(Sender: TObject);
begin
memo_dataLog.Lines.Add(GetDVDCreationDate(StrToInt(edit_sSize.Text)))
end;
我目前正在处理一个项目,需要知道刻录 DVD 的时间(刻录 DVD 的日期)。据我搜索和查找,发现所有此类数据都遵循 ISO 9660 格式,但我找不到如何访问或读取它,也尝试了一些相关的组件包和库,但是 none他们按照我的预期和需要工作。
也发现了这个 link:How to find out when a disc (DVD) has been written/burned? 但我找不到在 Delphi 中使用它们的方法。 它是如何工作的?
在 link 之后对此答案:How to find out when a disc (DVD) has been written/burned? 给出了在磁盘上读取日期和时间信息的位置:
读取 16 个字符加上从位置 33582 开始的一个附加字节,得出 DVD 创建时间为:
YYYYMMDDHHMMSSCCO
其中 CC 是厘秒,O 是以 15 分钟为间隔与 GMT 的偏移量,存储为 8 位整数(二进制补码表示)。
可以使用以下代码来阅读(另见How to read raw block from an USB storage device with Delphi?):
function GetDVDCreationDate: String;
// Sector size is 2048 on ISO9660 optical data discs
const
sector_size = 2048;
rdPos = (33582 DIV sector_size); // 33582
rdOfs = (33582 MOD sector_size) - 1;
var
RawMBR : array [0..sector_size-1] of byte;
btsIO : DWORD;
hDevice : THandle;
i : Integer;
GMTofs : ShortInt;
begin
Result := '';
hDevice := CreateFile('\.\E:', GENERIC_READ, // Select drive
FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if hDevice <> INVALID_HANDLE_VALUE then
begin
SetFilePointer(hDevice,sector_size * rdPos,nil,FILE_BEGIN);
ReadFile(hDevice, RawMBR[0], sector_size, btsIO, nil);
if (btsIO = sector_size) then begin
for i := 0 to 15 do begin
Result := Result + AnsiChar(RawMBR[rdOfs+i]);
end;
GMTofs := ShortInt(RawMBR[rdOfs+16]); // Handle GMT offset if important
end;
CloseHandle(hDevice);
end;
end;
请注意,从光盘读取原始数据必须从扇区大小的偶数位置开始。对于 ISO 9660 个磁盘,扇区大小为 2048。
感谢@LU RD 的回答,这里是他的代码,稍作修改:
function GetDVDCreationDate(sectorSize:integer): String;
// Sector size is 2048 on ISO9660 optical data discs
var
RawMBR : array [0..2047] of byte;
btsIO : DWORD;
hDevice : THandle;
i : Integer;
GMTofs : ShortInt;
rdPos, rdOfs: integer;
begin
rdPos := (33582 DIV sectorSize); // 33582
rdOfs := (33582 MOD sectorSize) - 1;
hDevice := CreateFile('\.\H:', GENERIC_READ, // Select drive
FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if hDevice <> INVALID_HANDLE_VALUE then
begin
SetFilePointer(hDevice,sectorSize * rdPos,nil,FILE_BEGIN);
ReadFile(hDevice, RawMBR[0], sectorSize, btsIO, nil);
for i := 0 to 15 do begin
Result := Result + AnsiChar(RawMBR[rdOfs+i]);
end;
GMTofs := ShortInt(RawMBR[rdOfs+16]); // Handle GMT offset if important
CloseHandle(hDevice);
end;
end;
//------------------------------------------------------------------------------
procedure Tfrm_main.btn_creationReadClick(Sender: TObject);
begin
memo_dataLog.Lines.Add(GetDVDCreationDate(StrToInt(edit_sSize.Text)))
end;