如何在c 中执行多个读/写HDD / USB字节

首先,我看了几个链接……

直接有效地读写硬盘扇区

在Windows上使用C语言读取硬盘驱动器上的特定扇区

我正在尝试做几乎相同的事情。 我遇到的问题是多次读取设备,因此我可以从DEVICE(USB)存储读取的字节,将它们写入文件。

这就是我想要做的……

  1. 声明变量
  2. 初始化变量
  3. SetFilePointer()
  4. ReadFile的()
  5. 将读取的字节输出到文件
  6. 使用ReadFile()来获取更多字节
  7. 再次将读取的字节输出到同一文件
  8. 重复6和7(实际上只重复4和5)

这似乎不起作用。 我想读取x个字节并将这些值存储到一个文件中然后读取更多并将这些值存储在上次相同的文件中。 我希望它重复这个过程,直到它读到设备的末尾。 我希望这个程序适用于任何大小的设备。 如果我可以把它放在循环中,那么我可以读写无限大小的设备。

这是一个如何读/写,所以我也想反过来。 读取文件中的值,然后将其写入设备。

我使用的是128MB USB。 它包含131858432字节。 如果需要更多信息,我会发布它,如果我有它。

我的代码:

#include  #include  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表示INVALID PARAMETER。

你的读取必须是扇区对齐的,所以你不能寻求偏移1,但只有0,sector_size,2 * sector_size,…,n * sector_size,你的读取也是扇区大小和你的内存缓冲区的倍数必须与sector_size对齐。

可以使用GetDiskFreeSpace检索扇区大小,并且可以使用VirtualAlloc获取对齐的内存。

也许你应该检查FSCTL_LOCK_VOLUME和FSCTL_DISMOUNT_VOLUME。

这是用于一次读取设备的其他代码

 #include  #include  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  #include  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:

这个问题在另一篇文章中没有得到回答。 这些post表示,答案不是该主题标题中问题的答案。 请仔细阅读标题。 提供的“答案”是关于SetFilePointer的。 这里的一个答案也不是答案。 这都是因为所谓的答案都不包含如何在C中读/写HDD / USB字节。

87表示INVALID PARAMETER。

你的读取必须是扇区对齐的,所以你不能寻求偏移1,但只有0,sector_size,2 * sector_size,…,n * sector_size,你的读取也是扇区大小和你的内存缓冲区的倍数必须与sector_size对齐。

可以使用GetDiskFreeSpace检索扇区大小,并且可以使用VirtualAlloc获取对齐的内存。

也许你应该检查FSCTL_LOCK_VOLUMEFSCTL_DISMOUNT_VOLUME

编辑

因为直接读取(或写入)没有缓冲,如果你想在更小的尺寸和扇区尺寸上操作,你必须自己处理缓冲。

该代码使用一个扇区缓冲方案实现从任意位置读取单个字节。 免责声明:需要通过测试。 小心可能的错误。

 #include  typedef __int64 int64; struct MyDevice { HANDLE handle; DWORD sector_size; int64 current_sector_position; void* sector_buffer; }; BOOL OpenMyDevice( struct MyDevice* device, const char* name ) { device->current_sector_position = -1; device->handle = INVALID_HANDLE_VALUE; device->sector_buffer = 0; { DWORD bytes_per_sector, unused1, unused2, unused3; // GetDiskFreeSpace doesn't like "\\.\". const char* name2 = name; if ( strncmp( name, "\\\\.\\", 4 ) == 0 ) name2 = name + 4; // For comaptibility reasons we will get logical sector size here. // For Vista+ it would be better to use DeviceIoControl with IOCTL_STORAGE_QUERY_PROPERTY. if ( !GetDiskFreeSpace( name2, &unused1, &bytes_per_sector, &unused2, &unused3 ) ) return FALSE; device->sector_size = bytes_per_sector; } device->sector_buffer = VirtualAlloc( 0, device->sector_size, MEM_COMMIT, PAGE_READWRITE ); if ( !device->sector_buffer ) return FALSE; device->handle = CreateFile( name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, // Can be zero, but in most cases it assumed by Windows. 0 ); if ( device->handle == INVALID_HANDLE_VALUE ) { VirtualFree( device->sector_buffer, 0, MEM_RELEASE ); device->sector_buffer = 0; return FALSE; } return TRUE; } // Call only when OpenDevice was successful. void CloseMyDevice( struct MyDevice* device ) { CloseHandle( device->handle ); device->handle = INVALID_HANDLE_VALUE; VirtualFree( device->sector_buffer, 0, MEM_RELEASE ); device->sector_buffer = 0; } BOOL LoadMyDeviceSector( struct MyDevice* device, int64 byte_offset ) { // Calculate sector position. int64 sector_position = ( byte_offset / device->sector_size ) * device->sector_size; if ( sector_position == device->current_sector_position ) // No need to load, it is in buffer return TRUE; { LARGE_INTEGER li; li.QuadPart = sector_position; if ( SetFilePointerEx( device->handle, li, 0, FILE_BEGIN ) ) { DWORD read; if ( ReadFile( device->handle, device->sector_buffer, device->sector_size, &read, 0 ) ) { if ( read == device->sector_size ) { device->current_sector_position = sector_position; return TRUE; } // else Hmmm. Maybe this is read beyond EOF? } } } // Cant guarantee that device->sector_buffer contains valid data. device->current_sector_position = -1; return FALSE; } BOOL LoadNextMyDeviceSector( struct MyDevice* device ) { DWORD read; device->current_sector_position = -1; if ( ReadFile( device->handle, device->sector_buffer, device->sector_size, &read, 0 ) ) { if ( read == device->sector_size ) return TRUE; // else Hmmm. Maybe this is read beyond EOF? } return FALSE; } BOOL SetMyDevicePos( struct MyDevice* device, int64 sector_aligned_byte_offset ) { LARGE_INTEGER li; li.QuadPart = sector_aligned_byte_offset; device->current_sector_position = -1; return SetFilePointerEx( device->handle, li, 0, FILE_BEGIN ); } int GetMyDeviceByte( struct MyDevice* device, int64 offset ) { if ( LoadMyDeviceSector( device, offset ) ) { // Calculate position in sector buffer. int64 offset_in_sector = offset - ( offset / device->sector_size ) * device->sector_size; return ((unsigned char*)( device->sector_buffer ))[ offset_in_sector ]; } return -1; } BOOL GetMyDeviceBytes( struct MyDevice* device, int64 byte_offset, void* dst_buffer, int64 count ) { char* dst = (char*) dst_buffer; int64 sector_position = ( byte_offset / device->sector_size ) * device->sector_size; int64 start = byte_offset - sector_position; // First loop pass can be unaligned! while ( count > 0 ) { if ( LoadMyDeviceSector( device, byte_offset ) ) { int64 chunk = device->sector_size - start; if ( chunk > count ) chunk = count; // chunk <= sector_size so conversion to int isn't harmful. memcpy( dst, ((char*)(device->sector_buffer)) + start, (int)chunk ); dst += chunk; byte_offset += chunk; count -= chunk; start = 0; // From now loop would be always sector_size aligned. } else return FALSE; } return TRUE; } int main( int argc, char* argv[] ) { struct MyDevice device = { INVALID_HANDLE_VALUE }; if ( OpenMyDevice( &device, "\\\\.\\K:" ) ) { // #1: Get one byte from device. { int byte = GetMyDeviceByte( &device, 11111 ); if ( byte >= 0 ) { } } // #2: Get multiple bytes from device. { char buff[1000]; if ( GetMyDeviceBytes( &device, 111111, buff, 1000 ) ) { } } // #3: Scan 100 sectors beginning from sector 111 for byte 155. { if ( SetMyDevicePos( &device, 111*device.sector_size ) ) { int i, j; for ( i = 0 ; i < 100 ; ++i ) { if ( !LoadNextMyDeviceSector( &device ) ) break; for ( j = 0 ; j < (int)device.sector_size ; ++j ) { int byte = ((unsigned char*)( device.sector_buffer ))[ j ]; if ( byte == 155 ) { // FOUND! } } } } } CloseMyDevice( &device ); } } 

GetMyDeviceByteGetMyDeviceBytes是针对小字节GetMyDeviceBytes的随机搜索。 如果有人需要按顺序传输大量数据,那么SetMyDevicePosLoadNextMyDeviceSector main #3快得多。

我更喜欢用C ++编写这段代码。