我通过phpMyAdmin创建了一个以pb00k
命名的表,SQL如下:
CREATE TABLE `pb00k` (
`k3y` int(255) NOT NULL AUTO_INCREMENT,
`n4m3` text NOT NULL,
`numb3r` text NOT NULL,
PRIMARY KEY (`k3y`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
因此它在包含此结构的
pb00k.frm
中生成一个mysql/data/
文件。现在我想用PHP从这个文件中得到这个结构。有可能吗?
最佳答案
是的,至少可以恢复部分信息。(为了其他读者的利益,问题的提出者已经意识到有更简单的方法可以获得列元数据)。
挑战在于.frm文件没有那么好的文档记录,因为一般社区很少需要破译它们。此外,文件的格式可能因操作系统而异。
但是,通过使用hexdump或类似的实用程序查看文件,您可以部分地了解正在发生的情况。然后,您可以更好地了解如何在PHP程序中读取文件并解码原始二进制数据。
不久前,我将此作为一个练习,并且能够恢复列数、列名和列类型。
下面是演示如何提取列名的示例。My.frm是一个表名“stops”,但您可以替换自己的.frm。
<?php
$fileName = "stops.frm";
// read file into an array of char
//---------------------------------
$handle = fopen($fileName, "rb");
$contents = fread($handle, filesize($fileName));
fclose($handle);
$fileSize=strlen($contents); // save the filesize fot later printing
// locate the column data near the end of the file
//-------------------------------------------------
$index = 6; // location of io_size
$io_size_lo = ord($contents[$index]);
$io_size_hi = ord($contents[$index+1]);
$io_size = $io_size_hi *0x100 + $io_size_lo; // read IO_SIZE
$index = 10; // location of record length
$rec_len_lo = ord($contents[$index]);
$rec_len_hi = ord($contents[$index+1]);
$rec_len = $rec_len_hi * 0x100 + $rec_len_lo; // read rec_length
// this formula uses io_size and rec_length to get to column data
$colIndex = ( ( (($io_size + $rec_len)/$io_size) + 1) * $io_size ) + 258;
$colIndex -= 0x3000; // this is not documented but seems to work!
// find number of columns in the table
//-------------------------------------------------
echo PHP_EOL."Col data at 0x".dechex($colIndex).PHP_EOL;
$numCols = ord($contents[$colIndex]);
//Extract the column names
//--------------------------------------
$colNameIndex = $colIndex+0x50; //0X50 by inspection
echo "Col names at 0x".dechex($colNameIndex).PHP_EOL;
$cols=array();
for ($col = 0; $col < $numCols; $col++){
$nameLen = ord($contents[$colNameIndex++]); // name length is at ist posn
$cols[]['ColumnName']= substr($contents,$colNameIndex,$nameLen-1); // read the name
$colNameIndex+=$nameLen+2; // skip ahead to next name (2 byte gap after \0)
}
print_r($cols);
这会让你开始。如果你认为我正在朝着正确的方向前进,我将在未来几天有时间的时候补充这一点。
编辑。我更新了代码,因此它应该适用于任何.frm文件(从表中)。当然,有一个免费的工具可以恢复mySQL(基于innoDB引擎),网址是https://github.com/twindb/undrop-for-innodb。在阅读了代码和相关的博客之后,他们没有使用.FRM文件进行恢复。同样的表信息也存储在innoDB字典中,他们使用它来恢复表格式等。
还有一种方法可以读取.FRM文件的内容。这里描述的是https://twindb.com/how-to-recover-table-structure-from-frm-files-online/。但是,他们正在使用mySQL读取.frm文件并从中重新创建表。
这里还有一个实用程序包https://www.mysql.com/why-mysql/presentations/mysql-utilities/包含一个.frm读取器。这是甲骨文做的,只有甲骨文知道.frm文件的格式!这个工具是免费的,所以你可以下载它。
Oracle发布了一些有关.frm文件格式的信息,但它既不完整又不正确!请参阅上一个堆栈问题。
https://dev.mysql.com/doc/internals/en/frm-file-format.html
现在,如果你还想自己分析.frm文件以获得乐趣或学习,那么你需要耐心,花时间去解开一个相当复杂的结构。如果你想继续尝试这是可以的,但给我你的.FRM文件(到sand_groper80@hotmail.com),这样我可以检查它,我会在几天内给你发送一些PHP代码,将提取一些额外的信息,如数据类型和显示大小。
关于php - 如何使用PHP从.frm文件获取表结构?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51852099/