【发布时间】:2018-03-17 10:52:35
【问题描述】:
首先,这是我查看的几个链接...
Read and write hard disk sector directly and efficiently
Read specific sector on hard drive using C language on windows
我正在尝试做几乎相同的事情。我遇到的问题是多次读取设备,因此我可以将读取的字节从设备(USB)存储到文件中。
这就是我想要做的......
- 声明变量
- 初始化变量
- SetFilePointer()
- 读取文件()
- 将读取的字节输出到文件中
- 使用 ReadFile() 获取更多字节
- 再次将读取的字节输出到同一个文件
- 重复 6 和 7(实际上只是重复 4 和 5)
这似乎不起作用。我想读取 x 个字节并将这些值存储到一个文件中,然后读取更多并将这些值存储在与上次相同的文件中。我希望它重复这个过程,直到它读到设备的末尾。我希望这个程序可以在任何尺寸的设备上运行。如果我可以把它放在一个循环中,那么我可以读写无限大小的设备。
这是一个如何读/写的方法,所以我也想反过来做。读取文件中的值,然后将它们写入设备。
我使用的是 128MB USB。它包含 131858432 个字节。如果需要更多信息,如果有的话我会发布。
我的代码:
#include <windows.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
BYTE sector[0x400] = {0};
DWORD bytesRead;
HANDLE device = NULL;
int numSector = 1;
int maxRead = 1;
FILE *readChar = fopen("G:\\usb_128MB_Dec2.txt", "w+");
device = CreateFile("\\\\.\\L:", // Drive to open
GENERIC_READ|GENERIC_WRITE, // Access mode
FILE_SHARE_READ|FILE_SHARE_WRITE, // Share Mode
NULL, // Security Descriptor
OPEN_EXISTING, // How to create
0, // File attributes
NULL); // Handle to template
if(device == INVALID_HANDLE_VALUE)
{
printf("CreateFile: %u\n", GetLastError());
system("pause");
return 1;
}
// set the file pointer for first time
SetFilePointer(device, numSector, NULL, FILE_BEGIN);
// Edit 1. Comment 2.
if(GetLastError() != NO_ERROR)
{
printf("GetLastError: %d\n", GetLastError());
goto end; // end: is before closing files or handles at end of main()
}
// read device for maxRead number of bytes and store the reading into a file
ReadFile(device, sector, maxRead, &bytesRead, NULL);
fprintf(readChar, "%d\n", sector[0]);
// This part of code does not act like expected
SetFilePointer(device, numSector, NULL, FILE_CURRENT);
if(!ReadFile(device, sector, maxRead, &bytesRead, NULL))
printf("err\n");
else
fprintf(readChar, "%d", sector[0]);
end: // Edit 1. Comment 2.
CloseHandle(device);
fclose(readChar);
system("pause");
return 0;
}
屏幕输出:
GetLastError: 87
文件输出:
Nothing is in the file.
该文件应该包含一个 8 位十进制值,而不是什么都没有或一个 0。
编辑 1:
87 表示无效参数。
您的读取必须是扇区对齐的,因此您不能寻求偏移 1, 但只有 0,sector_size,2*sector_size,...,n*sector_size,你读 也是扇区大小的倍数,并且您的内存缓冲区有 与扇区大小对齐。
可以使用 GetDiskFreeSpace 检索扇区大小并对齐 内存可以通过 VirtualAlloc 获得。
也许您还应该检查 FSCTL_LOCK_VOLUME 和 FSCTL_DISMOUNT_VOLUME。
这是用于一次读取设备的另一个代码
#include <windows.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
BYTE sector[0x200] = {0};
DWORD bytesRead;
HANDLE device = NULL;
int numSector = 1;
int maxRead = 0x200;
long long int i;
FILE *readChar = fopen("G:\\usb_128MB_Dec.txt", "w+");
device = CreateFile("\\\\.\\L:", // Drive to open
GENERIC_READ|GENERIC_WRITE, // Access mode
FILE_SHARE_READ|FILE_SHARE_WRITE, // Share Mode
NULL, // Security Descriptor
OPEN_EXISTING, // How to create
0, // File attributes
NULL); // Handle to template
if(device == INVALID_HANDLE_VALUE)
{
printf("CreateFile: %u\n", GetLastError());
system("pause");
return 1;
}
SetFilePointer(device, numSector, NULL, FILE_BEGIN);
if (!ReadFile(device, sector, maxRead, &bytesRead, NULL))
{
printf("ReadFile: %u\n", GetLastError());
goto end;
}
else
{
printf("Success!\n");
}
if(readChar == NULL)
{
printf("Did not open file. Exit 2.");
goto end;
}
for(i = 0; i < maxRead - 1; i++)
{
fprintf(readChar, "%d\n", sector[i]);
}
fprintf(readChar, "%d", sector[i]); // so the previous loop wont add \n to the last read wanted
end:
CloseHandle(device);
fclose(readChar);
system("pause");
return 0;
}
文件内容:
235
88
...
读取的每个字节都以十进制值存储在新的一行中。
所以可能更好地理解我想要做什么,这里是代码:
// What I want to do..
// This part works
SetFilePointer(device, numSector, NULL, FILE_BEGIN);
ReadFile(device, sector, maxRead, &bytesRead, NULL);
for(i = 0; i < size_of_device - 0x200; i += 512)
{
for(j = 0; j < maxRead; j++)
{
fprintf(readChar, "%d\n", sector[j]);
}
// stops working
SetFilePointer(device, numSector, NULL, FILE_CURRENT);
ReadFile(device, sector, maxRead, &bytesRead, NULL);
}
for(j = 0; j < maxRead - 1; j++)
{
fprintf(readChar, "%d\n", sector[j]);
}
fprintf(readChar, "%d", sector[j]);
// .. end of what i want to do
编辑2:现在正在多次阅读。
#include <windows.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
BYTE sector[0x200] = {0};
DWORD bytesRead;
HANDLE device = NULL;
//int numSector = 512; // original value was 1 not 512 but variable is not needed
int maxRead = 512;
int i, j, k = 0, l; // loop variables
FILE *readChar = fopen("G:\\wii u hdd image\\usb_128MB_Dec3.txt", "w+");
if(readChar == NULL)
{
printf("Error creating file.\n");
goto end;
}
device = CreateFile("\\\\.\\L:", // Drive to open
GENERIC_READ|GENERIC_WRITE, // Access mode
FILE_SHARE_READ|FILE_SHARE_WRITE, // Share Mode
NULL, // Security Descriptor
OPEN_EXISTING, // How to create
0, // File attributes
NULL); // Handle to template
// If device does not contain a handle value
if(device == INVALID_HANDLE_VALUE)
{
printf("Error. GetLastError: %u\n", GetLastError());
goto end;
}
for(i = 0; i < maxRead*503; i++) // maxRead * 503 = 257536
{
// If ReadFile() fails it will exit the program without adding a '\n' to the readChar file.
if(!ReadFile(device, sector, maxRead, &bytesRead, NULL))
{
printf("Error of ReadFile(). GetLastError(): %u\n", GetLastError());
goto end;
}
// If this is the first time through the loop then '\n' won't be added to the readChar file.
if(i != 0)
{
fprintf(readChar, "\n");
system("cls");
printf("%.2f%%\n", (i / 257536));
}
// Runs for 511 times. Then prints the 512th decimal value after the loop.
for(j = 0; j < maxRead - 1; j++)
{
fprintf(readChar, "%d\n", sector[j]);
}
fprintf(readChar, "%d", sector[j]);
}
end:
CloseHandle(device);
fclose(readChar);
system("pause");
return 0;
}
编辑 3:
此问题尚未在另一篇文章中得到解答。声明有答案的帖子不是该主题标题中问题的答案。请仔细阅读标题。提供的“答案”是关于 SetFilePointer。这里的唯一答案也不是答案。这都是因为没有一个假设的答案包含如何在 C 中读取/写入 HDD/USB 字节。
【问题讨论】:
-
阅读 MSDN for
ReadFile:“如果函数失败,或者正在异步完成,则返回值为零 (FALSE)。要获取扩展错误信息,请调用 GetLastError 函数。” - 我建议你试试 -
当您致电
SetFilePointer(device, 1, NULL, FILE_BEGIN)时,您想做什么?命名约定使您看起来像是要将文件指针设置为第二个扇区(扇区 1)的开头,但调用实际尝试做的是将文件指针设置为扇区零的第二个字节。同样,当您调用ReadFile并将maxRead设置为 1 时,我不清楚您是要读取单个字节还是整个扇区。 -
还要注意,在调用
SetFilePointer之后,如果返回值为INVALID_SET_FILE_POINTER,您应该只调用GetLastError。而且您的代码不会始终如一地检查错误。在代码的“一次性阅读”版本中对SetFilePointer的调用可能失败,您只是没有注意到。 -
SetFilePointer(device, numSector, NULL, FILE_BEGIN);我试图让它将指针设置为文件或设备的开头。我已将其删除,只是多次使用 ReadFile() 来获得所需的读数。 ReadFile() 会将指针移动读取的字节数。因此,在第一次读取 512 个字节并将其存储在 FILE *readChar 中之后,ReadFile() 将在再次使用时从原来的位置继续。 @HarryJohnston
-
如果您希望有人为您编写代码,那么您来错网站了。