【问题标题】:Ho to read ISO 9660 in Delphi?如何在 Delphi 中读取 ISO 9660?
【发布时间】:2016-05-29 12:35:37
【问题描述】:

我目前正在处理一个项目,并且需要知道刻录 DVD 的时间(刻录 DVD 的日期)。据我搜索和寻找,发现所有像这样的数据都遵循 ISO 9660 格式,但我找不到如何访问或阅读它,还尝试了一些相关的组件包和库,但它们都没有作为我期望和需要。

还找到了这个链接:How to find out when a disc (DVD) has been written/burned? 但我找不到在 Delphi 中使用它们的方法。 它是如何工作的?

【问题讨论】:

标签: delphi iso9660


【解决方案1】:

点击此答案的链接: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。

【讨论】:

  • 它很好,谢谢它,至少给了我一个线索......但它没有返回正确的答案,它会返回一个带有随机字符的字符串,如“#$%”或类似的东西......我认为问题在于扇区大小位置,但正如你所说的 ISO 9660 其 2048。
  • 正如我在 ISO 页面中看到的,有许多光学存储设备标准 - 包括 CD 和磁光设备 (MO):iso.org/iso/home/store/catalogue_ics/… 可以将它们刻录成 ISO 9660 以外的其他格式吗?如果是,那么如何识别?
  • @Armin,在几张可写数据 DVD 上测试了我的答案,效果很好。请注意,您需要识别正确的驱动器标签。
  • 我知道驱动器标签
  • @LURD 太棒了!+1 不过我建议在ReadFile() 之后和for 循环之前添加一点:if btsIO &lt;&gt; 2048 then Result := 'Error' else。开头至少有一个Result := '';
【解决方案2】:

感谢@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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 2014-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多