稀疏文件(sparse-files)生成汇总

稀疏文件文件这个东东,最开始知道是在学Oracle temp表空间。因为 Oracle 临时表空间的数据文件ls和du出来,大小不一致,后来才知道,

这东东是稀疏文件的特性。 这玩意主要是先跟系统把整个文件大小空间申请下来,然后再在需要时把数据向里面填。 好处是一次性分配连续空间,

避免了硬盘碎片。 坏处是,后续文件扩展有可能没有相应的空间, 结果向临时表空间文件放数据,就有可能会发现硬盘空间不够了。 所以有些DBA为了

防止出现这种问题,创建出Oracle的 临时表空间数据文件后,用命令将其转为非稀疏文件。

因为最近整批量生成测试文件东东,又整理了下这个东东。

(一)  命令行方式生成方式及与普通文件的相互转换

(二) 压缩时的小问题

()  Linux下代码生成

()  Windows下代码生成


(一)  命令行方式生成及与普通文件的相互转换

Windows下没找到直接生成稀疏文件的命令,UNIX/Linux没找到直接生成非稀疏文件的命令,郁闷。

UNIX/Linux用dd命令就行了。

dd if=/dev/zero of=xcl.sparsefile bs=1M seek=1000 count=0 

       //除了dd,在Solaris上,还可以用mkfile命令来创建
mkfile -n 10m /u01/xcl.sparsefile

//查看文件内容
od -t a /u01/xcl.sparsefile

//查看文件实际大小

du -k /u01/xcl.sparsefile


// 将稀疏文件转为非稀疏

cp --sparse=never /u01/app/oracle/oradata/xcldb/temp_xcl.dbf 

//将普通文件转为稀疏文件

cp --sparse=always /u01/xcl.nosparsefile /u01/xcl.sparsefile


(二) 压缩时的小问题

     稀疏文件压缩时,一定要记得在tar中加S参数,不然解压出来就不是稀疏文件了。
tar zcSf temp_xcl.tar.gz /u01/app/oracle/oradata/xcldb/temp_xcl.dbf 


()  Linux下代码生成

主要是有fsetpos来移到到指定大小位置,再用fwrite来占位。  也可以用lseek来实现。

    本来当时在Linux下弄完这个代码,想Windows下应当也一样,没想到效果不同。 

   再就是fpost_t 的使用,区别比较大,要注意。

/*************************************************
Author: xiongchuanliang
Description: 非Windows下生成指定大小的稀疏文件
**************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define PRINT_ERROR printf("error : %d:%s",errno,strerror(errno))

int testSparseFile(const char * fname)
{

 FILE *fp = NULL;
 fpos_t pos ;
 char buf[255] ={0};
 if( (fp = fopen(fname,"w+")) == NULL)
 {
  printf("err: fopen() \n");
  PRINT_ERROR;
  return -1;
 }
 
 // Linux 设置fpos_t 用这个结构体
 pos.__pos = 0x100000; //1024 == 1mb
 // Windows 在vc下fpos_t被定义为long型,则是直接赋值就可以了。
 // 但生成出来的文件是非稀疏的。
 // pos  = 0x100000 ;
 
 if( fsetpos( fp, &pos ) != 0 )
 {
	printf("err: fsetpos() \n");
	PRINT_ERROR;
	return -1;
 }

 if( (fwrite("\0",1,1,fp)) != 1)
 {
	 printf("err: fwrite() \n");
	 PRINT_ERROR;
	 return -1;
 }

 fclose( fp );
 return 0;
}


int main()
{
const char * fname ="/u01/xcl.sparsefile";
//const char * fname ="C:\\xcl\\demo5.nosparsefile";
char cmdbuf[50] = {0};
sprintf(cmdbuf,"ls -l %s ; du %s ;",fname,fname);
testSparseFile(fname);
system(cmdbuf);
return 0;
}

( 四)  Windows下代码生成

     Windows下生成稀疏文件的关键是 DeviceIoControl 函数。但在XP下使用麻烦不断。

要定义_WIN32_WINNT大于等于0x0500才能使用FSCTL_SET_SPARSE. 
 可参考:

http://msdn.microsoft.com/zh-cn/subscriptions/aa364596

/*************************************************
Author: xiongchuanliang
Description: Windows下生成指定大小的文件,非稀疏文件
**************************************************/

#include <stdlib.h>
#include <stdio.h>

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif

#include <Windows.h>
#include <Winioctl.h>
#include <direct.h> // _mkdir
#include <io.h>

void PrintError(DWORD dwErr) {
	char szMsg[256];
	DWORD dwFlags = FORMAT_MESSAGE_IGNORE_INSERTS |
		FORMAT_MESSAGE_MAX_WIDTH_MASK |
		FORMAT_MESSAGE_FROM_SYSTEM;
	if (!::FormatMessageA(dwFlags, NULL, dwErr, 0, szMsg, sizeof(szMsg), NULL)) strcpy(szMsg, "Unknown error.");
	printf(szMsg);
	printf("\n");
}

int testfile()
{
	HANDLE hFile ;
	DWORD dwWriteaddr = 0;
	DWORD dwRet =0,dwFPos = 0;
	BOOL bRet = FALSE;
	hFile = CreateFileA("C:\\xcl\\demo4.txt",GENERIC_READ|GENERIC_WRITE,
		FILE_SHARE_READ|FILE_SHARE_WRITE,
		NULL,
		CREATE_ALWAYS,
		0,
		NULL);
	if(hFile == INVALID_HANDLE_VALUE)
	{
		printf("创建文件失败!\n");
		PrintError(GetLastError());
		return 1;
	}

	//告诉系统该文件是稀疏文件,将文件中那些0字节空间给压缩掉
	bRet = DeviceIoControl(hFile,
		FSCTL_SET_SPARSE,
		NULL,
		0,
		NULL,
		0,
		&dwRet,
		NULL);
	if(!bRet)
	{
		printf("DeviceIoControl发生错误.\n");
		PrintError(GetLastError());
		return 1;
	}

	//生成指定大小的文件
	// 0x100000 = 1048576 = 1 MB
	dwFPos = SetFilePointer(hFile,0x100000,NULL,FILE_BEGIN);
	if (dwFPos == INVALID_SET_FILE_POINTER)
	{
		printf("SetFilePointer发生错误.\n");
		PrintError(GetLastError());
		return 1;
	}

	bRet = WriteFile(hFile,"XCL\0",4,&dwWriteaddr,NULL);
	if (!bRet)
	{
		printf("WriteFile发生错误.\n");
		PrintError(GetLastError());
		return 1;
	}

	//除了在文件最末尾会有"XCL"这三个字符外,其它部份将会被填上0,实实在在的占用系统空间.
	dwFPos = SetEndOfFile(hFile);
	if (dwFPos == INVALID_SET_FILE_POINTER)
	{
		printf("SetEndOfFile发生错误.\n");
		PrintError(GetLastError());
		return 1;
	}

	//GetFileInformationByHandle 可查看文件是否为稀疏文件(sparse-files)
	BY_HANDLE_FILE_INFORMATION stFileInfo;
	GetFileInformationByHandle(hFile, &stFileInfo);
	if(stFileInfo.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE)
	{
		//Sparse file
		printf("稀疏文件 \n");
	}else{
		//Not sparse file
		printf("非稀疏文件 \n");
	}

	CloseHandle(hFile);
	return 0;
}


int main(void)
{
	testfile();

	system("pause");

	return 0;
}


MAIL: xcl_168@aliyun.com

Blog: http://blog.csdn.net/xcl168

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值