Home > ソフトウェア > MagicPNG > MagicPNG100.zip > Src > sslib > SplitFile.cpp
//SplitFile.cpp //ファイル分割/結合 #include"../StdAfx.h" #include"sslib.h" #include<ctype.h> namespace sslib{ namespace splitfile{ //splitFile() const long split_buffer_size=(1<<20)*5; const long split_max_part=999+26*26*26; #ifndef DISABLE_FILE //ファイルを分割する(分割サイズまたは分割数指定による) //分割サイズは1024b、10k、100mの様に指定(10kb、100mbでも可) //分割数は6,12の様に単位を付加せず指定すること split::RESULT splitFile(const TCHAR* file_name,const TCHAR* param,const TCHAR* output_dir){ long long split_size=0; long long* split_sizes=NULL; long long chunks=0; bool by_count=false; if(file_name==NULL||param==NULL){ return split::CANNOT_OPEN; } File src_file; if(!src_file.open(file_name)){ return split::CANNOT_OPEN; } //分割数指定 by_count=isdigit(param[lstrlen(param)-1])!=0; ((!by_count)?split_size:chunks)=strex::filesize2longlong(param); if((!by_count&&split_size<1)|| (by_count&&chunks<2)){ return split::INVALID_PARAM; } long long src_file_size; src_file_size=src_file.getSize(); if(src_file_size<=split_size){ return split::NOT_NECESSARY; } if(chunks>split_max_part|| (chunks==0&&src_file_size/split_size>split_max_part)){ return split::TOO_MANY; } if(chunks>0){ split_sizes=new long long[(DWORD)chunks]; for(int ii=0;ii<chunks;ii++){ //小数点以下を切り捨てた数値を配列に代入 split_sizes[ii]=src_file_size/chunks; } if(src_file_size%chunks!=0){ //割り切れなければ、先頭のファイルから1バイトずつファイルサイズを増やす for(int i=0;i<chunks;i++){ split_sizes[i]++; long long total=0; for(int ii=0;ii<chunks;ii++){ total+=split_sizes[ii]; } //割り切れればループを抜ける if(src_file_size%total==0)break; } } } TCHAR* file_buffer=new TCHAR[split_buffer_size]; if(file_buffer==NULL){ if(chunks)SAFE_DELETE_ARRAY(split_sizes); return split::MALLOC_ERR; } long long total_written=0; tstring base_path; if(output_dir!=NULL){ base_path=path::addTailSlash(output_dir); base_path+=path::getFileName(file_name); }else{ base_path=file_name; } tstring output_path; for(long i=0;;i++){ long long dest_file_size=0; DWORD read_size=0,written_size=0; File dest_file; output_path=base_path+_T(".")+path::createPartExtension(i+1); if(!dest_file.open(output_path.c_str(),OPEN_ALWAYS)){ return split::CANNOT_CREATE; } if(chunks>0)split_size=split_sizes[i]; for(dest_file_size=0,read_size=split_buffer_size;dest_file_size<split_size;dest_file_size+=read_size){ if(read_size>split_size-dest_file_size)read_size=(DWORD)(split_size-dest_file_size); written_size=src_file.read(file_buffer,read_size); total_written+=written_size; if(written_size<=0)break; written_size=dest_file.write(file_buffer,written_size); } if(written_size<=0||total_written==src_file_size)break; } if(chunks)SAFE_DELETE_ARRAY(split_sizes); SAFE_DELETE_ARRAY(file_buffer); return split::SUCCESS; } #endif //分割ファイルの先頭ファイルかどうか //拡張子が000、001、0000、00001、000000など //分割ファイルならばその拡張子の桁数を取得 bool isSplitFile(const TCHAR* file_name,int* p_digit){ bool result=false; //拡張子の桁数 int digit=0; int dot_pos=str::locateLastCharacter(file_name,'.'); if(dot_pos!=-1){ tstring ext=path::getExtension(file_name); if(ext[ext.length()-1]=='0'||ext[ext.length()-1]=='1'){ //拡張子末尾が'0'か'1'であれば digit++; if(ext.length()==1){ //'.0'の様に一桁である場合 result=true; }else{ for(size_t i=2;i<=ext.length();i++){ if(ext[ext.length()-i]=='0'){ digit++; result=true; }else{ //'0'以外の数字があるため先頭ファイルではない result=false; digit=0; break; } } } } } if(p_digit)*p_digit=digit; return result; } #ifndef DISABLE_FILE //ファイルを結合する join::RESULT joinFile(const TCHAR* file_name,const TCHAR* output_dir){ int digit=0; if(!isSplitFile(file_name,&digit))return join::NOT_SPLIT; tstring src_path; tstring dest_path; tstring base_path(file_name); int dot_pos=str::locateLastCharacter(file_name,'.'); if(file_name==NULL||dot_pos==-1){ return join::NOT_SPLIT; } base_path=path::removeExtension(base_path); if(output_dir!=NULL){ dest_path=path::addTailSlash(output_dir)+=path::getFileName(base_path); }else{ dest_path=base_path; } File dest_file; if(!dest_file.open(dest_path.c_str(),CREATE_ALWAYS)){ return join::CANNOT_CREATE; } TCHAR* file_buffer=new TCHAR[split_buffer_size]; if(file_buffer==NULL){ return join::MALLOC_ERR; } for(long i=0;;i++){ DWORD dest_file_size=0,written_size=0; src_path=base_path+_T(".")+path::createPartExtension(i,digit); File src_file; if(!src_file.open(src_path.c_str())){ //拡張子'00...0'が存在しない場合以外は分割ファイル終端とみなす if(i!=0)break; else continue; } while((written_size=src_file.read(file_buffer,split_buffer_size))){ dest_file.write(file_buffer,written_size); dest_file_size+=written_size; } } SAFE_DELETE_ARRAY(file_buffer); return join::SUCCESS; } #endif //分割ファイルのリストを作成 bool makeSplitFileList(std::list<tstring>* file_list,const TCHAR* file_name){ bool result=false; int digit=0; if(!isSplitFile(file_name,&digit))return false; for(long i=0;;i++){ tstring src_path(path::removeExtension(file_name)); src_path=src_path+_T(".")+path::createPartExtension(i,digit); if(!path::fileExists(src_path.c_str())){ //拡張子'00...0'が存在しない場合以外は分割ファイル終端とみなす if(i!=0)break; else continue; } file_list->push_back(src_path); result=true; } return result; } #ifndef DISABLE_FILEO_PERATION //分割ファイルを削除 bool removeSplitFile(const TCHAR* file_name,bool recycle_bin){ std::list<tstring> file_list; if(!makeSplitFileList(&file_list,file_name)|| file_list.empty())return false; bool result=false; for(std::list<tstring>::iterator ite=file_list.begin(), end=file_list.end(); ite!=end; ++ite){ if(recycle_bin){ result=fileoperation::moveToRecycleBinSH(ite->c_str()); }else{ result=::DeleteFile(ite->c_str())!=0; } } return result; } #endif //namespace splitfile } //namespace sslib }
Home > ソフトウェア > MagicPNG > MagicPNG100.zip > Src > sslib > SplitFile.cpp