开发者

Create contiguous file using C#?

Is it possible to create a large (physically) contiguous file on a disk using C#? Preferably using only managed code, but if it's not possi开发者_运维百科ble then an unmanaged solution would be appreciated.


Any file you create will be logically contiguous.

If you want physically contiguous you are on OS and FS territory. Really (far) beyond the control of normal I/O API's.

But what will probably come close is to claim the space up-front: create an Empty stream and set the Length or Position property to what you need.


Writing a defragger?

It sounds like you're after the defragmentation API anyway:-

http://msdn.microsoft.com/en-us/library/aa363911%28v=vs.85%29.aspx

The link from the bottom, cos it seems you've missed the C# wrapper that someone has kindly produced.

http://blogs.msdn.com/b/jeffrey_wall/archive/2004/09/13/229137.aspx


With modern file systems it is hard to ensure a contiguous file on the hard disk. Logically the file is always contiguous, but the physical blocks that keep the data vary from file system to file system.

The best bet for this would be to use an old file system (ext2, FAT32, etc.) and just ask for a large file using seek to the file size you want and then flushing this file. More up-to-date file systems will probably mark a large file size, but won't actually write anything to the hard disk, instead returning zeros on a future read without actually reading.

int fileSize = 1024 * 1024 * 512;
FileStream file = new FileStream("C:\\MyFile", FileMode.Create, FileAccess.Write);
file.Seek(fileSize, SeekOrigin.Begin);
file.Close();


To build a database, you will need to use the scatter-gather I/O functions provided by the Windows API. This is a special type of file I/O that allows you to either "scatter" data from a file into memory or "gather" data from memory and write it to a contiguous region of a file. While the buffers into which the data is scattered or from which it is gathered need not be contiguous, the source or destination file region is always contiguous.

This functionality consists of two primary functions, both of which work asynchronously. The ReadFileScatter function reads contiguous data from a file on disk and writes it into an array of non-contiguous memory buffers. The WriteFileGather function reads non-contiguous data from memory buffers and writes it to a contiguous file on disk. Of course, you'll also need the OVERLAPPED structure that is used by both of these functions.

This is exactly what SQL Server uses when it reads and writes to the database and/or its log files, and in fact this functionality was added to an early service pack for NT 4.0 specifically for SQL Server's use.

Of course, this is pretty advanced level stuff, and hardly for the faint of heart. Surprisingly, you can actually find the P/Invoke definitions on pinvoke.net, but I have an intensely skeptical mistrust of the site. Since you'll need to spend a lot of quality time with the documentation just to understand how these functions work, you might as well write the declarations yourself. And doing it from C# will create a whole host of additional problems for you, such that I don't even recommend it. If this kind of I/O performance is important to you, I think you're using the wrong tool for the job.

The poor man's solution is contig.exe, a single-file defragmenter available for free download here.


In short no then

The OS will do this in the background, what i would do is make the file as big as you expect it to be, that way the OS will place it contigously. And if you need to grow the file, you again grow it by like 10% each time. This is simular to how a SQL server keeps it database files.

Open opening the FileStream you open it with append.

Example:

FileStream fwriter = new FileStream("C:\\test.txt", FileMode.Append,     FileAccess.Write, FileShare.Read);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜