当我使用代码:blocks运行gcc
时,它会在F上创建registration.txt(如果它不存在)并写入密码和用户名,但是当我在使用Microsoft Visual Studio编译器的项目中使用它时,它什么都不做。
例如,如果我调用此函数,例如:Write("JohnDoe", "password123")
,在文件registration.txt中应该出现在一行:JohnDoe, password123
。
const char *FILEPATH = "F:\\registration.txt";
int Write(char *username, char *password) {
if (username == NULL || password == NULL) {
return -1;
}
BOOL error = TRUE;
size_t lengthUsername = strlen(username);
size_t lengthPassword = strlen(password);
LPDWORD bytesUsernameWritten = 0;
char comma[2] = ",";
char newLine[3] = "\r\n";
LPDWORD bytesPasswordWritten = 0;
LPDWORD bytesWrittenComma = 0;
//if the file doesn't exist, we create it
HANDLE file = CreateFile((LPCWSTR)FILEPATH, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE) {
if (GetLastError() != ERROR_FILE_EXISTS) {
printf("0x%x", GetLastError());
CloseHandle(file);
return -1;
} //the file exist, we try to create it
file = CreateFile((LPCWSTR)FILEPATH, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE) {
printf("Couldn't open the file. Error : 0x%x", GetLastError());
CloseHandle(file);
return -1;
}
}
//We try to write the username and the password in file, each combination on each line, in this format: username, password
error = WriteFile(file, username, (DWORD)lengthUsername, bytesUsernameWritten, NULL);
if (error == FALSE) {
printf("The username couldn't have been written. Error 0x%x\n", GetLastError());
CloseHandle(file);
return -1;
}
error = WriteFile(file, comma, 1, bytesWrittenComma, NULL);
if (error == FALSE) {
printf("The comma couldn't have been written. Error 0x%x\n", GetLastError());
CloseHandle(file);
return -1;
}
error = WriteFile(file, password, (DWORD)lengthPassword, bytesPasswordWritten, NULL);
if (error == FALSE) {
printf("The password couldn't have been written. Error 0x%x\n", GetLastError());
CloseHandle(file);
return -1;
}
error = WriteFile(file, newLine, 2, bytesPasswordWritten, NULL);
if (error == FALSE) {
printf("The endline couldn't have been written. Error 0x%x\n", GetLastError());
CloseHandle(file);
return -1;
}
CloseHandle(file);
return 0;
}
您的主要问题是使用Unicode和ASCII之间的混淆。
所有采用字符串参数的Windows API函数都有两个版本:一个适用于LPCSTR
,另一个适用于LPCWSTR
。
您可以将char *
强制转换为LPCSTR
并使用ASCII版本CreateFileA
,但是您无法将其强制转换为LPCWSTR
并使用CreateFileW
- CreateFile
的Unicode版本,因为它需要UCS-16编码中的字符串,其中每个字符占用2个字节。
调用哪个版本的函数取决于编译器标志。对于Windows上的CodeBlocks,默认使用ASCII版本,因此您的功能有效。对于VS,默认值为Unicode,因此文件路径字符串变得混乱并且不会创建文件。
此外,您还有两个其他错误:
WriteFile
错误。
第四个参数是一个指针,其中WriteFile
存储写入的字节数。
您正在传递一个NULL指针,因为您将bytesUsernameWritten
等变量设置为0.但是根据MS documentation,如果最后一个参数lpOverlapped
不是NULL,则只能使用NULL。
你应该做的是,将bytesUsernameWritten
声明为DWORD并使用&
运算符传递其地址。
否则,即使函数成功创建文件,也不会获得写入的字节数。INVALID_HANDLE_VALUE
这是不必要的,但幸运的是它不会让你的程序崩溃。最后,没有理由尝试两次打电话给CreateFile
。只需使用OPEN_ALWAYS
参数调用一次。这将打开一个现有文件,但如果该文件不存在,它将自动创建它而不是失败。