2016-08-18 136 views
-1

我有下面的代碼,它創建兩個文件。當最後一個4455字節的寫入操作被調用時,它返回0作爲寫入的字節數。這可能是由於順序掃描的dwFlagAttributes和沒有緩衝?Win32 WriteFile返回0字節作爲寫入的字節數。 lpBuffer包含4455字節

hIn = CreateFile (fIn, GENERIC_READ, 0, NULL, OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL | SSF | NBF, NULL); 

Desired Access: Generic Read 
Disposition: Open 
Options: Sequential Access, No Buffering, Synchronous IO Non-Alert, Non-Directory File 
Attributes: N 
ShareMode: None 
AllocationSize: n/a 
OpenResult: Opened 

hOut = CreateFile (fOut, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 
        FILE_ATTRIBUTE_NORMAL | SSF | NBF, NULL); 

Desired Access: Generic Write, Read Attributes 
Disposition: OverwriteIf 
Options: Sequential Access, No Buffering, Synchronous IO Non-Alert, Non-Directory File 
Attributes: N 
ShareMode: None 
AllocationSize: 0 
OpenResult: Created  

創建文件後,會有一個while循環讀取file1。然後將這些字節寫入file2。 file1大約是13MB。

while (ReadFile (hIn, aBuffer, BUF_SIZE, &nIn, NULL) && nIn > 0 && WriteOK) { 
     for (iCopy = 0; iCopy < nIn; iCopy++) 
      ccBuffer [iCopy] = (BYTE)((aBuffer [iCopy] + shift) % 256); 
     WriteOK = WriteFile (hOut, ccBuffer, nIn, &nOut, NULL); 
    } 

從下面的反彙編中可以看出,最後4455個字節沒有寫入file2。這可能是由於CreateFile dwFlagAttributes?

0:000> kb 
# ChildEBP RetAddr Args to Child 
00 0018bd00 00411612 00000038 0018bdf8 00001167 kernel32!WriteFile 
01 0018fe64 0041144c 00273a99 00273ac9 0000000a cci!cci_f+0x162 
02 0018ff44 00411bbb 00000004 00273a78 002723e8 cci!main+0x6c 
03 0018ff88 7698336a 7efde000 0018ffd4 77c29f72 cci!__tmainCRTStartup+0x122 
04 0018ff94 77c29f72 7efde000 76d02536 00000000 kernel32!BaseThreadInitThunk+0xe 
05 0018ffd4 77c29f45 00411122 7efde000 00000000 ntdll!__RtlUserThreadStart+0x70 
06 0018ffec 00000000 00411122 7efde000 00000000 ntdll!_RtlUserThreadStart+0x1b 

0:000> dd 0018bd00 la 
0018bd00 0018fe64 00411612 00000038 0018bdf8 
0018bd10 00001167 0018fe34 00000000 0018ff44 
0018bd20 0018fe78 00000000 

0:000> $number of bytes to be written 0x1167 
0:000> .formats 00001167 
Evaluate expression: 
    Hex:  00001167 
    Decimal: 4455 
    Octal: 00000010547 
    Binary: 00000000 00000000 00010001 01100111 
    Chars: ...g 
    Time: Wed Dec 31 20:14:15 1969 
    Float: low 6.24278e-042 high 0 
    Double: 2.20106e-320 

0:000> gu 
eax=00000000 ebx=00000000 ecx=76b2df07 edx=00000057 esi=0018bd1c edi=0018fe64 
eip=00411612 esp=0018bd1c ebp=0018fe64 iopl=0   nv up ei pl zr na pe nc 
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b    efl=00000246 
cci!cci_f+0x162: 
00411612 cmp  esi,esp 

0:000> $number of bytes written 
0:000> dd 0018fe34 l1 
0018fe34 00000000 

enter image description here

+0

如果'WriteFile'失敗,請調用'GetLastError'來找出原因。 –

+0

@JonathanPotter我得到一個無效的參數傳遞給參數或函數。這對我來說並不清楚,因爲之前在循環中操作成功。寫入文件的唯一參數變化是字節數和緩衝區的大小 – dcrearer

+0

我創建了一個文件80kb(81920),正如David所述,寫入操作成功進行正確對齊。 – dcrearer

回答

4

既然你寫非緩衝,你需要堅持到這裏記錄的對齊要求:https://msdn.microsoft.com/en-us/library/windows/desktop/cc644950.aspx

具體文件訪問必須在量的倍數啓動扇區大小,並且其大小是卷扇區大小的倍數。您的4455大小的緩衝區不符合第二個要求。

當然,如果你想寫這些最後4455字節,並沒有更多,那麼你在窘境。您需要將其四捨五入成卷扇區大小的倍數,然後填寫實際的4455字節,然後填充。將文件指針設置回這些4455字節的末尾,並調用SetEndOfFile

+1

你可能想說一些關於明顯的後續問題(文件不應該包含填充字節),可能通過提及'SetEndOfFile'函數。 –

+0

最後的4455個字節是源文件中的剩餘字節。所以,如果我理解正確的話,我將不得不將4455四捨五入成爲矢量大小的倍數。有趣的反饋 – dcrearer

+0

這是正確的 –