Solved

Problem with creating an empty/blank file above 1.16GB

Posted on 2011-09-28
1
449 Views
Last Modified: 2016-09-29
So, i'm trying to create a file that is... lets say 2GB, but when i use the routine i wrote, the file is 1.16GB, how do i avoid this limit ?


procedure TDAPClass.CreateBlankFile(
const FilePath: String );
const
  TmpFileBuffer : Byte = ($00);
  dwFlagsAndAttr = FILE_FLAG_RANDOM_ACCESS;
var
  hTmpFile      : THandle;
  nBytesWritten : DWORD;
  I             : Integer;
begin
  // Create a temp blank file
  hTmpFile := CreateFile(
  PChar( FilePath ),
  GENERIC_WRITE,
  0,
  nil,
  CREATE_ALWAYS,
  FILE_ATTRIBUTE_TEMPORARY or dwFlagsAndAttr,
  0 );
  for I := 0 to Pred(nConnections) do
  begin
    // seek to given offset
    SetFilePointer(
     hTmpFile, i64EndOffset[I] - 1, nil, FILE_BEGIN );
    Sleep(500);
    // Write 1 byte in current offset
    WriteFile(
     hTmpFile, TmpFileBuffer, SizeOf(TmpFileBuffer), nBytesWritten, nil );
    Sleep(500);
  end;
  // Close Temp file handle
  CloseHandle( hTmpFile );
end;

Open in new window

0
Comment
Question by:rotem156
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
1 Comment
 
LVL 25

Accepted Solution

by:
epasquier earned 500 total points
ID: 36890614
SetFilePointer has a weird way of managing size parameters. It takes the size in 2 different ways :
- movement is a signed 32 bits integer, in first parameter after handle, second param not used (=nil) :
=> MAX = 2GB -1 .
So this method will fail if you try to put unsigned size equal or above 2GB.
- movement is a signed 64 bits integer : first param takes the low order part, and second parameter takes a pointer to the highest order part. That is the weird part, the pointer. See how I managed it in code.

You will ask as myself first did : why so complex ? why a pointer in 2nd parameter ? well, because if this was not a pointer, seeing that they made a single function with 2 functioning modes, you would have problem with 64 bits sizes between $80000000 (2GB) and $FFFFFFFF (4GB-1) because then high order part would be nul, AND first part would have to be considered SIGNED, not UNSIGNED.

Of course, they could have replaced all that with a single 64 bits signed value, even if that meant separate that in 2 params, but without pointer stuff and 2 functioning modes. But that would have broken existing 32bits only code using the API.

One last note : Delphi Seek & Truncate functions, which would be the equivalent of the method used below, have the same restriction with the 2GB-1 limit, or you'll end up with I/O error #131 :  ERROR_NEGATIVE_SEEK

Here is how to do that properly :

procedure CreateBlankFile(const FilePath: String; Size:int64 );
Var
 hTmpFile:THandle;
const
 dwFlagsAndAttr = FILE_FLAG_RANDOM_ACCESS;
begin
 hTmpFile := CreateFile( PChar( FilePath ),
  GENERIC_WRITE, 0, nil, CREATE_ALWAYS,
  FILE_ATTRIBUTE_TEMPORARY or dwFlagsAndAttr, 0 );
 try
  if Size>=$80000000
   Then SetFilePointer( hTmpFile, Size {And $FFFFFFFF}, Pointer(Cardinal(@Size)+4), FILE_BEGIN )
   Else SetFilePointer( hTmpFile, Size, nil, FILE_BEGIN );
  SetEndOfFile( hTmpFile );
 finally
  CloseHandle( hTmpFile );
 end;
end;

Open in new window

0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Delphi selector screen 2 97
enhance the following code 3 54
How to Get Images From Server to Client using App Tethering 1 57
Problem working with dynamic array - help 2 48
A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

739 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question