<p>WMI报告驱动器比实际大小小几MB。我认为这与Windows如何处理汽缸/磁头/扇区有关。在</p>
<p>我的解决方案是读取超过报告的驱动器大小的末尾,直到出现错误:</p>
<pre><code>import wmi
disks = wmi.WMI().Win32_DiskDrive(MediaType="Removable Media")
for disk in disks:
disk_size = int(disk.size)
sector_size = disk.BytesPerSector
print(disk.name, "reported size:", disk_size)
with open(disk.name, "rb") as f:
f.seek(disk_size)
while True:
try:
f.read(sector_size)
disk_size += sector_size
except PermissionError:
break
print(disk.name, "readable size:", disk_size)
</code></pre>
<p>对于两个不同的32GB SD卡,我得到以下结果:</p>
^{pr2}$
<p>但是,实际的驱动器实际上还有1024到2048个字节,我们仍然无法读取,我不确定如何获取它们。但是,这比我们之前丢失的几个MB要好。在</p>
<p><strong>编辑:</strong>似乎是<a href="https://docs.python.org/3.4/library/io.html#io.DEFAULT_BUFFER_SIZE" rel="nofollow">buffering</a>导致了读取最后几个字节的问题。如果我这样做,我可以读取剩余的字节<code>open(disk.name, "rb", buffering=0)</code>。但是,这是非常慢的(大约1MB/秒,相当于其中一个驱动器大约7秒)。可能有一种很好的混合方法,只使用buffering=0读取最后几个字节,其余时间使用默认缓冲。在</p>
<pre><code>\\.\PHYSICALDRIVE2 reported size: 31683778560
\\.\PHYSICALDRIVE2 readable size: 31691112448 (with buffering=0)
\\.\PHYSICALDRIVE14 reported size: 31437020160
\\.\PHYSICALDRIVE14 readable size: 31439454208 (with buffering=0)
</code></pre>
<p><strong>编辑2:</strong>您可以使用<code>read1</code>获得最后几个字节,而不需要用<code>buffering=0</code>打开文件。因此,要获得实际磁盘大小,可以执行以下操作:</p>
<pre><code>reported_size = disk.size
f.seek(reported_size)
while True:
try: # Read beyond the reported size
f.read(sector_size)
except PermissionError:
easily_readable_size = f.tell()
try: # Get the last few bytes using read1 (unbuffered)
for i in range(128): # Test up to this many additional sectors
f.read1(self.sector_size)
except PermissionError:
actual_size = f.tell()
break
</code></pre>
<p>注意,我认为您可能不总是能够<code>f.read</code>直到<code>easily_readable_size</code>,因为内部缓冲区的对齐方式可能并不总是相同的(?)。我把这个值减少了<code>io.DEFAULT_BUFFER_SIZE</code>,这样更安全一些。然后我用我自己的函数重写<code>f.read</code>,该函数将上述内容组合起来,从而在整个磁盘上透明地{<cd4>}。这样一来,<code>f.read</code>就和你期望的一样工作。在</p>