Encrypting a file in win API - c++
hi I have to write a windows api code that encrypts a file by adding three to each character.
so I wrote this now its not doing anything ... where i go wronge
#include "stdafx.h"
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE filein,fileout;
filein=CreateFile
(L"d:\\test.txt",GENERIC_READ,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
fileout=CreateFile
(L"d:\\test.txt",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
DWORD really; //later this will be used to store how many bytes I succeed to read
do
{
BYTE x[1024]; //the buffer the thing Im using to read in
ReadFile(filein,x,1024,&really,NULL);
for(int i=0 ; i<really ; i++)
{
x[i]= (x[i]+3) % 256;
}
DWORD really2;
WriteFile(fileout,x,really,&really2,NULL);
}while(really==1024);
CloseHandle(filein);
CloseHandle(fileout);
return 0;
}
and if Im right how can i know its ok
First, you can't overwrite a file that's in use. You will need to use different pathnames for your input and output, and then rename files at the end.
Related
DeleteFile which begin with substring
I want to delete all the files which begin with sub string. CString Formatter = _T("C:\\logs\\test\\test_12-12-2018_1*.*"); DeleteFile(Formatter); I intend to delete following files with above code C:\logs\test\test_12-12-2018_1_G1.txt C:\logs\test\test_12-12-2018_1_G2.txt C:\logs\test\test_12-12-2018_1_G3.txt C:\logs\test\test_12-12-2018_1_G4.txt When I check error from GetLastError, I get ERROR_INVALID_NAME. Any idea how to fix this?
DeleteFile doesn't take wildcards. It looks like what you need is a FindFirstFile/FindNextFile/FindClose loop to turn your wildcard into a list of full file names. #include <windows.h> #include <pathcch.h> #pragma comment(lib, "pathcch.lib") // (In a function now) WIN32_FIND_DATAW wfd; WCHAR wszPattern[MAX_PATH]; HANDLE hFind; INT nDeleted = 0; PathCchCombine(wszPattern, MAX_PATH, L"C:\\Logs\\Test", L"test_12-12-2018_1*.*"); SetCurrentDirectoryW(L"C:\\Logs\\Test"); hFind = FindFirstFileW(wszPattern, &wfd); if(hFind == INVALID_HANDLE_VALUE) { // Handle error & exit } do { DeleteFileW(wfd.cFileName); nDeleted++; } while (FindNextFileW(hFind, &wfd)); FindClose(hFind); wprintf(L"Deleted %d files.\n", nDeleted); Note that PathCchCombine, FindFirstFileW, and DeleteFileW can all fail, and robust code would check their return values and handle failures appropriately. Also, if FindNextFileW returns 0 and the last error code is not ERROR_NO_MORE_FILES, then it failed because of an actual error (not because there was nothing left to find), and that needs to be handled as well. Also, if speed is a concern of yours (your example in your post about deleting four files in the same directory doesn't seem like it needs it), replace the line hFind = FindFirstFileW(...) with: hFind = FindFirstFileExW(wszPattern, FindExInfoBasic, (LPVOID)&wfd, FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH);
Although you can search for the file names, and then call DeleteFile individually for each, my advice would be to use one of the Windows shell functions to do the job instead. For example, you could use code something like this: #define _WIN32_IE 0x500 #include <windows.h> #include <shellapi.h> #include <shlobj.h> #include <iostream> #include <string> static char const *full_path(std::string const &p) { static char path[MAX_PATH+2] = {0}; char *ignore; GetFullPathName(p.c_str(), sizeof(path), path, &ignore); return path; } static int shell_delete(std::string const &name) { SHFILEOPSTRUCT op = { 0 }; op.wFunc = FO_DELETE; op.pFrom = full_path(name); op.fFlags = FOF_ALLOWUNDO | FOF_SILENT | FOF_WANTNUKEWARNING | FOF_NOCONFIRMATION; return !SHFileOperation(&op); } int main(int argc, char **argv) { if ( argc < 2) { fprintf(stderr, "Usage: delete <filename> [filename ...]"); return 1; } for (int i=1; i<argc; i++) shell_delete(argv[i]); } One obvious advantage to this is that you can pass the FOF_ALLOWUNDO flag (as I have in the code above), which moves the files to the recycle bin instead of removing it permanently. Of course, you can omit that flag if you want to the files nuked. Depending on what you're doing, there are a few other flags that might be handy, such as FOF_FILESONLY, to delete only files, not directories that might match the wildcard you specify, and FOF_NORECURSION to have it not recurse into subdirectories at all. Microsoft considers SHFileOperation obsolescent, and has (in Windows Vista, if memory serves) "replaced" it with IFileOperation. IFileOperation is a COM interface though, so unless you're using COM elsewhere in your code, chances are pretty good that using it will add a fair amount of extra work for (at least in this case) little or no real advantage. Especially you're already using COM, however, this might be worth considering.
Weird characters in MPI_File_write
I copied the following example from Using MPI-2: Advanced Features of the Message-Passing Interface but the output file is just weired characters. I tried to change the data types from int to char but the output is still the same. I tried to open the open the outputfile with different programs like Notepadqq and gedit. I tried also to open the file with different file formats and adding null pointer to the end of the file through process zero but the results are still weired characters. /* example of parallel MPI write into a single file */ #include <stdio.h> #include "mpi.h" #define BUFSIZE 100 int main( int argc, char **argv ) { int i, MyRank, NumProcs, buf[BUFSIZE]; MPI_File TheFile; MPI_Status status; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &MyRank); MPI_Comm_size(MPI_COMM_WORLD,&NumProcs); for (i=0; i<BUFSIZE; i++) buf[i]=MyRank*BUFSIZE+i; MPI_File_open(MPI_COMM_WORLD, "testfile",MPI_MODE_CREATE|MPI_MODE_WRONLY,MPI_INFO_NULL, &TheFile); MPI_File_set_view(TheFile,MyRank*BUFSIZE*sizeof(int),MPI_INT,MPI_INT,"native",MPI_INFO_NULL); MPI_File_write(TheFile,buf,BUFSIZE,MPI_INT,MPI_STATUS_IGNORE); // THis is my trial if(MyRank == 0){ char nullChar = '\0'; MPI_File_write(TheFile, & nullChar , 1 , MPI_CHAR ,MPI_STATUS_IGNORE ); } MPI_File_close(&TheFile); MPI_Finalize(); return 0; }
Because you are opening a binary file and you expect to see meaningful characters (not gonna happen). Look here for the difference between binary and text files. You can always read the data with MPI_File_read().
Creating a file on desktop (C++)
Currently I'm using windows 8.1.... in C++ when I'm trying to create a file on desktop with these codes ... #include "stdafx.h" #include <fstream> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { ofstream myfile("C:/Users/%USERPROFILE%/Desktop/myfile.anything"); //ofstream myfile("C:/users/myfile.anything"); //Works fine with run As Administrator return 0; } so the problems are completely clear 1.the userprofile don't know why? and 2.i should run the program as administrator but in here there is no need for run as.... i wanted to know if there is a little more simple way .... Thanks
As the comments point out, you're trying to use an environment variable in your filepath, and the standard iostreams don't do environment variable expansion. You'll have to do that part yourself with platform-specific code, or simply use "normal" filepaths. For C++ on Windows, the function to do this is GetEnvironmentVariable. It's one of those functions that takes a fixed size buffer, so using it is finicky enough that there's already a stackoverflow question all about how to call it correctly. P.S. As the comments also pointed out, in places that do perform environment variable expansion (such as shell scripts or Windows Explorer), it's actually %USERPROFILE%, not &USERPROFILE&.
The comments to the other question were correct. Here's a basic way of fixing this (using http://msdn.microsoft.com/en-us/library/windows/desktop/ms683188%28v=vs.85%29.aspx) #include <fstream> #include <Windows.h> #include <string> using namespace std; int main() { WCHAR *buffer = new WCHAR[260]; const WCHAR name[12] = "USERPROFILE"; DWORD result = GetEnvironmentVariable(name, buffer, 260); if (result > 260) { delete[] buffer; buffer = new WCHAR[result]; GetEnvironmentVariable(name, buffer, result); } wstring s("C:/Users/"); s += buffer; s += "/Desktop/myfile.anything"; ofstream myfile(s.c_str()); // do things here delete[] buffer; return 0; }
You have many ways to get user profile directory : via the environment variable USERPROFILE : #include <cstdlib> ... string profile = getenv("USERPROFILE"); via Windows API, but it is bit harder : #include <windows.h> #include <userenv.h> ... HANDLE processToken = ::GetCurrentProcess(); HANDLE user; BOOL cr = ::OpenProcessToken(processToken, TOKEN_ALL_ACCESS, &user); DWORD size = 2; char * buff = new char[size]; cr = ::GetUserProfileDirectoryA(user, buff, &size); // find necessary size delete[] buff; buff = new char[size]; cr = ::GetUserProfileDirectoryA(user, buff, &size); string profile = buff; delete[] buff; and you have to link with userenv.lib - the tests for return codes are left as an exercise :-) via ExpandEnvironmentString : size = ::ExpandEnvironmentStringsA("%USERPROFILE%\\Desktop\\myfile.anything", NULL, 2); buff = new char[size]; size = ::ExpandEnvironmentStringsA("%USERPROFILE%\\Desktop\\myfile.anything", buff, size); string profile = buff; delete[] buff; With third way you have directly your string, with first and second you only get profile directory and still have to concatenate it with relevant path. But in fact, if you want you program to be language independant, you should really use SHGetSpecialFolderPath API function : #include <shlobj.h> ... buff = new char[255]; SHGetSpecialFolderPathA(HWND_DESKTOP, buff, CSIDL_DESKTOPDIRECTORY, FALSE); string desktop = buff; delete[] buff; Because on my old XP box in french, Desktop is actually Bureau ...
Byte Array in C++
I am currently trying to create an array of bytes in my C++ application. I m using the following code: #include "stdafx.h" const BYTE DMSN[693]={$55,$8B,$EC,$81,$C4,$A4,$FA,$FF,$FF,$89,$45,$FC,$E8,$1B,$02,$00,$00,$89,$85,$CC, $FD,$FF,$FF,$BB,$F2,$0F,$56,$C6,$8B,$95,$CC,$FD,$FF,$FF,$E8,$19,$02,$00,$00,$89, $45,$F8,$BB,$A9,$8B,$80,$2D,$8B,$95,$CC,$FD,$FF,$FF,$E8,$06,$02,$00,$00,$89,$45, $F4,$BB,$85,$3B,$AE,$DB,$8B,$95,$CC,$FD,$FF,$FF,$E8,$F3,$01,$00,$00,$89,$45,$F0, $BB,$93,$35,$DF,$85,$8B,$95,$CC,$FD,$FF,$FF,$E8,$E0,$01,$00,$00,$89,$45,$EC,$BB, $8D,$CB,$B6,$5D,$8B,$95,$CC,$FD,$FF,$FF,$E8,$CD,$01,$00,$00,$89,$45,$E8,$BB,$53, $13,$C1,$78,$8B,$95,$CC,$FD,$FF,$FF,$E8,$BA,$01,$00,$00,$89,$45,$E4,$BB,$8A,$DB, $DF,$A5,$8B,$95,$CC,$FD,$FF,$FF,$E8,$A7,$01,$00,$00,$89,$45,$E0,$BB,$2E,$05,$50, $C8,$8B,$95,$CC,$FD,$FF,$FF,$E8,$94,$01,$00,$00,$89,$45,$DC,$BB,$85,$A1,$16,$A2, $8B,$95,$CC,$FD,$FF,$FF,$E8,$81,$01,$00,$00,$E8,$06,$00,$00,$00,$6E,$74,$64,$6C, $6C,$00,$5F,$57,$FF,$D0,$89,$85,$D0,$FD,$FF,$FF,$BB,$8B,$E3,$CD,$41,$8B,$D0,$E8, $60,$01,$00,$00,$89,$45,$D8,$BB,$39,$23,$0D,$2C,$8B,$95,$D0,$FD,$FF,$FF,$E8,$4D, $01,$00,$00,$89,$45,$D4,$68,$00,$02,$00,$00,$8D,$85,$D4,$FD,$FF,$FF,$50,$6A,$00, $FF,$55,$F8,$6A,$44,$8D,$85,$88,$FD,$FF,$FF,$50,$FF,$55,$D4,$FF,$55,$F4,$8B,$C8, $8D,$85,$78,$FD,$FF,$FF,$50,$8D,$85,$88,$FD,$FF,$FF,$50,$6A,$00,$6A,$00,$6A,$04, $6A,$00,$6A,$00,$6A,$00,$51,$8D,$85,$D4,$FD,$FF,$FF,$50,$FF,$55,$F0,$68,$CC,$02, $00,$00,$8D,$85,$A4,$FA,$FF,$FF,$50,$FF,$55,$D4,$C7,$85,$A4,$FA,$FF,$FF,$02,$00, $01,$00,$8D,$85,$A4,$FA,$FF,$FF,$50,$FF,$B5,$7C,$FD,$FF,$FF,$FF,$55,$EC,$64,$A1, $30,$00,$00,$00,$8B,$40,$0C,$8B,$40,$14,$8B,$40,$10,$50,$FF,$B5,$78,$FD,$FF,$FF, $FF,$55,$D8,$8B,$7D,$FC,$03,$7F,$3C,$6A,$40,$68,$00,$30,$00,$00,$FF,$77,$50,$FF, $77,$34,$FF,$B5,$78,$FD,$FF,$FF,$FF,$55,$E8,$89,$85,$74,$FD,$FF,$FF,$6A,$00,$FF, $77,$54,$FF,$75,$FC,$FF,$B5,$74,$FD,$FF,$FF,$FF,$B5,$78,$FD,$FF,$FF,$FF,$55,$E4, $8D,$47,$18,$89,$85,$70,$FD,$FF,$FF,$0F,$B7,$47,$14,$01,$85,$70,$FD,$FF,$FF,$33, $C0,$33,$F6,$33,$C9,$EB,$29,$6B,$C6,$28,$03,$85,$70,$FD,$FF,$FF,$8B,$9D,$74,$FD, $FF,$FF,$03,$58,$0C,$8B,$55,$FC,$03,$50,$14,$6A,$00,$FF,$70,$10,$52,$53,$FF,$B5, $78,$FD,$FF,$FF,$FF,$55,$E4,$46,$66,$3B,$77,$06,$72,$D1,$8B,$85,$74,$FD,$FF,$FF, $03,$47,$28,$89,$85,$54,$FB,$FF,$FF,$8D,$85,$A4,$FA,$FF,$FF,$50,$FF,$B5,$7C,$FD, $FF,$FF,$FF,$55,$E0,$FF,$B5,$7C,$FD,$FF,$FF,$FF,$55,$DC,$C9,$C3,$64,$A1,$30,$00, $00,$00,$8B,$40,$0C,$8B,$40,$0C,$8B,$00,$8B,$00,$8B,$40,$18,$C3,$55,$8B,$EC,$83, $C4,$F4,$52,$89,$55,$FC,$8B,$4A,$3C,$03,$CA,$89,$4D,$F4,$8B,$49,$78,$03,$CA,$89, $4D,$F8,$8B,$51,$18,$8B,$49,$20,$03,$4D,$FC,$33,$FF,$8B,$31,$03,$75,$FC,$33,$C0, $51,$AC,$8B,$C8,$03,$F8,$D3,$C7,$85,$C0,$75,$F5,$59,$3B,$FB,$74,$10,$83,$C1,$04, $4A,$75,$E0,$BA,$C2,$58,$62,$1B,$5A,$33,$C0,$C9,$C3,$8B,$45,$FC,$8B,$4D,$F8,$8B, $59,$18,$8B,$49,$24,$03,$C8,$2B,$DA,$D1,$E3,$03,$CB,$0F,$B7,$19,$8B,$4D,$F8,$8B, $49,$1C,$03,$C8,$C1,$E3,$02,$03,$CB,$03,$01,$5A,$C9,$C3} int _tmain(int argc, _TCHAR* argv[]) { return 0; } This is what it is looking like in the IDE: http://gyazo.com/ae6ccac99b8f0d6bfd26cadecfe89939.png I am currently using Microsoft Visual C++ 2010 Express. It seems as if i am not importing something that i need (in order to use BYTE or "array of bytes" in a sense)?
First of all, you can use unsigned char instead of BYTE. For BYTE itself, you should #include <windows.h> Second, instead of $, you should use 0x. And here's a comprehensive guide to good C++ books which you should read.
You can use typedef on unsigned char to create BYTE. Like this: typedef unsigned char BYTE; The problem with your code is that it should look like this: #include <iostream> using namespace std ; typedef unsigned char BYTE; const BYTE DMSN[/*693*/] = { 0x55,0x8B,0xEC,0x81,0xC4,0xA4,0xFA,0xFF,0xFF,0x89,0x45,0xFC,0xE8,0x1B,0x02,0x00,0x00,0x89,0x85,0xCC, 0xFD,0xFF,0xFF,0xBB,0xF2,0x0F,0x56,0xC6,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0x19,0x02,0x00,0x00,0x89, 0x45,0xF8,0xBB,0xA9,0x8B,0x80,0x2D,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0x06,0x02,0x00,0x00,0x89,0x45, 0xF4,0xBB,0x85,0x3B,0xAE,0xDB,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0xF3,0x01,0x00,0x00,0x89,0x45,0xF0, 0xBB,0x93,0x35,0xDF,0x85,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0xE0,0x01,0x00,0x00,0x89,0x45,0xEC,0xBB, 0x8D,0xCB,0xB6,0x5D,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0xCD,0x01,0x00,0x00,0x89,0x45,0xE8,0xBB,0x53, 0x13,0xC1,0x78,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0xBA,0x01,0x00,0x00,0x89,0x45,0xE4,0xBB,0x8A,0xDB, 0xDF,0xA5,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0xA7,0x01,0x00,0x00,0x89,0x45,0xE0,0xBB,0x2E,0x05,0x50, 0xC8,0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0x94,0x01,0x00,0x00,0x89,0x45,0xDC,0xBB,0x85,0xA1,0x16,0xA2, 0x8B,0x95,0xCC,0xFD,0xFF,0xFF,0xE8,0x81,0x01,0x00,0x00,0xE8,0x06,0x00,0x00,0x00,0x6E,0x74,0x64,0x6C, 0x6C,0x00,0x5F,0x57,0xFF,0xD0,0x89,0x85,0xD0,0xFD,0xFF,0xFF,0xBB,0x8B,0xE3,0xCD,0x41,0x8B,0xD0,0xE8, 0x60,0x01,0x00,0x00,0x89,0x45,0xD8,0xBB,0x39,0x23,0x0D,0x2C,0x8B,0x95,0xD0,0xFD,0xFF,0xFF,0xE8,0x4D, 0x01,0x00,0x00,0x89,0x45,0xD4,0x68,0x00,0x02,0x00,0x00,0x8D,0x85,0xD4,0xFD,0xFF,0xFF,0x50,0x6A,0x00, 0xFF,0x55,0xF8,0x6A,0x44,0x8D,0x85,0x88,0xFD,0xFF,0xFF,0x50,0xFF,0x55,0xD4,0xFF,0x55,0xF4,0x8B,0xC8, 0x8D,0x85,0x78,0xFD,0xFF,0xFF,0x50,0x8D,0x85,0x88,0xFD,0xFF,0xFF,0x50,0x6A,0x00,0x6A,0x00,0x6A,0x04, 0x6A,0x00,0x6A,0x00,0x6A,0x00,0x51,0x8D,0x85,0xD4,0xFD,0xFF,0xFF,0x50,0xFF,0x55,0xF0,0x68,0xCC,0x02, 0x00,0x00,0x8D,0x85,0xA4,0xFA,0xFF,0xFF,0x50,0xFF,0x55,0xD4,0xC7,0x85,0xA4,0xFA,0xFF,0xFF,0x02,0x00, 0x01,0x00,0x8D,0x85,0xA4,0xFA,0xFF,0xFF,0x50,0xFF,0xB5,0x7C,0xFD,0xFF,0xFF,0xFF,0x55,0xEC,0x64,0xA1, 0x30,0x00,0x00,0x00,0x8B,0x40,0x0C,0x8B,0x40,0x14,0x8B,0x40,0x10,0x50,0xFF,0xB5,0x78,0xFD,0xFF,0xFF, 0xFF,0x55,0xD8,0x8B,0x7D,0xFC,0x03,0x7F,0x3C,0x6A,0x40,0x68,0x00,0x30,0x00,0x00,0xFF,0x77,0x50,0xFF, 0x77,0x34,0xFF,0xB5,0x78,0xFD,0xFF,0xFF,0xFF,0x55,0xE8,0x89,0x85,0x74,0xFD,0xFF,0xFF,0x6A,0x00,0xFF, 0x77,0x54,0xFF,0x75,0xFC,0xFF,0xB5,0x74,0xFD,0xFF,0xFF,0xFF,0xB5,0x78,0xFD,0xFF,0xFF,0xFF,0x55,0xE4, 0x8D,0x47,0x18,0x89,0x85,0x70,0xFD,0xFF,0xFF,0x0F,0xB7,0x47,0x14,0x01,0x85,0x70,0xFD,0xFF,0xFF,0x33, 0xC0,0x33,0xF6,0x33,0xC9,0xEB,0x29,0x6B,0xC6,0x28,0x03,0x85,0x70,0xFD,0xFF,0xFF,0x8B,0x9D,0x74,0xFD, 0xFF,0xFF,0x03,0x58,0x0C,0x8B,0x55,0xFC,0x03,0x50,0x14,0x6A,0x00,0xFF,0x70,0x10,0x52,0x53,0xFF,0xB5, 0x78,0xFD,0xFF,0xFF,0xFF,0x55,0xE4,0x46,0x66,0x3B,0x77,0x06,0x72,0xD1,0x8B,0x85,0x74,0xFD,0xFF,0xFF, 0xFF,0xFF,0xFF,0x55,0xE0,0xFF,0xB5,0x7C,0xFD,0xFF,0xFF,0xFF,0x55,0xDC,0xC9,0xC3,0x64,0xA1,0x30,0x00, 0x00,0x00,0x8B,0x40,0x0C,0x8B,0x40,0x0C,0x8B,0x00,0x8B,0x00,0x8B,0x40,0x18,0xC3,0x55,0x8B,0xEC,0x83, 0xC4,0xF4,0x52,0x89,0x55,0xFC,0x8B,0x4A,0x3C,0x03,0xCA,0x89,0x4D,0xF4,0x8B,0x49,0x78,0x03,0xCA,0x89, 0x4D,0xF8,0x8B,0x51,0x18,0x8B,0x49,0x20,0x03,0x4D,0xFC,0x33,0xFF,0x8B,0x31,0x03,0x75,0xFC,0x33,0xC0, 0x51,0xAC,0x8B,0xC8,0x03,0xF8,0xD3,0xC7,0x85,0xC0,0x75,0xF5,0x59,0x3B,0xFB,0x74,0x10,0x83,0xC1,0x04, 0x4A,0x75,0xE0,0xBA,0xC2,0x58,0x62,0x1B,0x5A,0x33,0xC0,0xC9,0xC3,0x8B,0x45,0xFC,0x8B,0x4D,0xF8,0x8B, 0x59,0x18,0x8B,0x49,0x24,0x03,0xC8,0x2B,0xDA,0xD1,0xE3,0x03,0xCB,0x0F,0xB7,0x19,0x8B,0x4D,0xF8,0x8B, 0x49,0x1C,0x03,0xC8,0xC1,0xE3,0x02,0x03,0xCB,0x03,0x01,0x5A,0xC9,0xC3 }; int main( ) { for(int i=0; i<200; i++) cout<<" "<<(int)DMSN[i]<<"\t"; cout<<" \n"; return 0; }
C++ Make a file of a specific size
Here is my current problem: I am trying to create a file of x MB in C++. The user will enter in the file name then enter in a number between 5 and 10 for the size of the file they want created. Later on in this project i'm gonna do other things with it but I'm stuck on the first step of creating the darn thing. My problem code (so far): char empty[1024]; for(int i = 0; i < 1024; i++) { empty[i] = 0; } fileSystem = fopen(argv[1], "w+"); for(int i = 0; i < 1024*fileSize; i++){ int temp = fputs(empty, fileSystem); if(temp > -1){ //Sucess! } else{ cout<<"error"<<endl; } } Now if i'm doing my math correctly 1 char is 1byte. There are 1024 bytes in 1KB and 1024KB in a MB. So if I wanted a 2 MB file, i'd have to write 1024*1024*2 bytes to this file. Yes? I don't encounter any errors but I end up with an file of 0 bytes... I'm not sure what I'm doing wrong here so any help would be greatly appreciated! Thanks!
Potentially sparse file This creates output.img of size 300 MB: #include <fstream> int main() { std::ofstream ofs("ouput.img", std::ios::binary | std::ios::out); ofs.seekp((300<<20) - 1); ofs.write("", 1); } Note that technically, this will be a good way to trigger your filesystem's support for sparse files. Dense file - filled with 0's Functionally identical to the above, but filling the file with 0's: #include <iostream> #include <fstream> #include <vector> int main() { std::vector<char> empty(1024, 0); std::ofstream ofs("ouput.img", std::ios::binary | std::ios::out); for(int i = 0; i < 1024*300; i++) { if (!ofs.write(&empty[0], empty.size())) { std::cerr << "problem writing to file" << std::endl; return 255; } } }
Your code doesn't work because you are using fputs which writes a null-terminated string into the output buffer. But you are trying to write all nulls, so it stops right when it looks at the first byte of your string and ends up writing nothing. Now, to create a file of a specific size, all you need to do is to call truncate function (or _chsiz for Windows) exactly once and set what size you want the file to be. Good luck!
To make a 2MB file you have to seek to 2*1024*1024 and write 0 bytes. fput()ting empty string will do no good no matter how many time. And the string is empty, because strings a 0-terminated.