SHGetFolderPathW not working with japanese username - c++

Im trying to create one file in %APPDATA% using SHGetFolderPathW function. This function I guess is getting chars in unicode. I'm working with Visual Studio 2010 little project. The following code work in english version of win 8 but not in japanese version (username is japanese):
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <windows.h>
#include <Shlobj.h>
#include <tchar.h>
#include <string>
int _tmain(int argc, _TCHAR* argv[])
{
std::wstring output = L"";
WCHAR* folder = new WCHAR[2048];
SHGetFolderPathW(NULL, CSIDL_APPDATA,
NULL, SHGFP_TYPE_CURRENT, folder
);
std::wstring str1 = folder;
str1 += L"\\hola.txt";
std::wcout << str1 << std::endl;
std::string str(str1.begin(), str1.end());
std::cout << str << std::endl;
// Create file in folder
FILE * file;
char *path = new char[str.length()+1];
strcpy(path, str.c_str());
file = fopen (path, "w");
fputs ("Hello World",file);
fclose (file);
system("PAUSE");
return 0;
}
The code is showing good path in English version, but in japanese, this path isn't right. I wonder if I have any way to use SHGetFolderPath in all languages. I'm googling two days but not solution found.

If you have a wide string file path, use wide string version of fopen. This should work:
#include <string>
#include <stdio.h>
#include <Shlobj.h>
#include <tchar.h>
int _tmain(int argc, _TCHAR* argv[])
{
WCHAR folder[MAX_PATH];
SHGetFolderPathW(NULL, CSIDL_APPDATA,
NULL, SHGFP_TYPE_CURRENT, folder
);
std::wstring str1 = folder;
str1 += L"\\hola.txt";
// Create file in folder
FILE * file;
file = _wfopen (str1.c_str(), L"w");
fputs ("Hello World",file);
fclose (file);
return 0;
}

Related

C++ Read UTF-8 (Lithuanian letters) symbols from txt file and show them in console application [duplicate]

This question already has answers here:
Read Unicode UTF-8 file into wstring
(7 answers)
Closed 1 year ago.
I need you help.
I'm using Windows 10 and Visual Studio Community compiler.
I managed to get Lithuanian letter to show on C++ console application using wstring and wcout.
#include <iostream>
#include <io.h>
#include <fcntl.h>
using namespace std;
int main()
{
_setmode(_fileno(stdout), _O_U16TEXT);
wstring a = L"ąėėąčėį";
wcout << a;
return 0;
}
Result is exactly what I wanted it to be
Now I want my program to read Lithuanian letters from Info.txt file.
This is how far I managed to get.
#include <iostream>
#include <fstream>
#include <io.h>
#include <fcntl.h>
#include <string>
using namespace std;
int main()
{
_setmode(_fileno(stdout), _O_U16TEXT);
wstring text;
wifstream fin("Info.txt");
getline(fin, text);
wcout << text;
return 0;
}
Returned string in console application shows different simbols.
But the returned string in console application shows different simbols.
In my belief a possible solution
I need to add L before the text like in previous example with wcout.
wstring a = L"ąėėąčėį";
But I'm still just learning C++ and I don't know how to do so in example with Info.txt
I need your help!
UTF8 needs std::ifstream, not wifstream. The latter is used in Windows as UTF16 file storage (not recommended in any system)
You can use SetConsoleOutputCP(CP_UTF8) to enable UTF8 printing, but that can run in to problems, specially in C++ 20
Instead, call _setmode and convert UTF8 to UTF16.
Make sure notepad saves the file in UTF8 (encoding option is available in Save window)
#include <iostream>
#include <fstream>
#include <string>
#include <io.h>
#include <fcntl.h>
#include <Windows.h>
std::wstring u16(const std::string u8)
{
if (u8.empty()) return std::wstring();
int size = MultiByteToWideChar(CP_UTF8, 0, u8.c_str(), -1, 0, 0);
std::wstring u16(size, 0);
MultiByteToWideChar(CP_UTF8, 0, u8.c_str(), -1, u16.data(), size);
return u16;
}
int main()
{
(void)_setmode(_fileno(stdout), _O_U16TEXT);
std::string text;
std::ifstream fin("Info.txt");
if (fin)
while (getline(fin, text))
std::wcout << u16(text) << "\n";
return 0;
}

write system call unix doesn't write all text from argv [duplicate]

This question already has answers here:
Different answers from strlen and sizeof for Pointer & Array based init of String [duplicate]
(4 answers)
Closed 3 years ago.
I'm trying to write out data that the user entered into argv[2]. I have to use write() system call (unix)
for Example I enter "hi there" but "hi th" is written out into the file instead of the whole text.
#include <iostream>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
using namespace std;
using std::cout;
using std::endl;
int main(int argc, char *argv[])
{
int fd, fileWrite;
char *file = argv[1]; //file to be create
char *text = argv[2]; //text stored here
fd = open(file, O_WRONLY | O_APPEND | O_CREAT);
//write message from command line
fileWrite = write(fd, text, sizeof(text));
fileWrite = write(fd, "\n", 1);
if(fileWrite == -1){
perror("fileWrite");
}
//close file
close(fd);
return 0;
}`
Use strlen(text) in<string.h> instead of sizeof(text) to determine the length of the string, sizeof(text) will return you the size of a pointer, which is always the same.

reading a UTF-16 file in Linux

I have the following program which reads a file into a string buffer.
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
constexpr int BUFSIZE = 1024;
int main(int argc, char *argv[])
{
std::ifstream ifs(argv[1], std::ifstream::binary);
if(!ifs)
return 1;
string buffer(BUFSIZE, L'\0');
ifs.read(&buffer[0], BUFSIZE);
cerr << ifs.gcount() << endl;
return 0;
}
It prints out the expected 1024.
The following program which is supposed to read into a wstring buffer doesn't work though.
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
constexpr int BUFSIZE = 1024;
int main(int argc, char *argv[])
{
std::wifstream ifs(argv[1], std::ifstream::binary);
if(!ifs)
return 1;
wstring buffer(BUFSIZE, L'\0');
ifs.read(&buffer[0], BUFSIZE);
cerr << ifs.gcount() << endl;
return 0;
}
Ir prints out 0 with the same file.
As you can see the only difference is changing the stream to a wstream and the buffer to a wstring.
I've tried both g++ 8.2.1 and clang++ 6.0.1 under OpenSUSE Tumbleweed.
Where is the problem/my error?
You should be using std::basic_ifstream<char16_t> and std::u16string for UTF-16. std::wifstream and std::wstring are not appropriate because the width of wchar_t is implementation defined. In Linux in particular, it is (usually?) 32 bits wide.
Same for character literals. You should use u'\0' etc. instead of L'\0'.

c++ FindFirstFile Cannot convert const char to basic_string

FindFirstFile function somehow doesn't accept my wstring (nor string) to be passed as a parameter.
I get a compiler error
Cannot convert const char[9] to std::basic_string
#include "stdafx.h"
#include <string>
#include <iostream>
#include <stdio.h>
#include <Windows.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
wstring path = "C:\\*.dmp";
WIN32_FIND_DATA dataFile;
HANDLE hFind;
hFind = FindFirstFile (path.c_str(), &dataFile);
cout << "The name of the first found file is %s \n" dataFile.cFileName << endl;
FindClose hFind;
getchar();
return 0;
}
I get a compiler error
Cannot convert const char[9] to std::basic_string
You need a wide char literal to initialize a std::wstring properly:
wstring path = L"C:\\*.dmp";
// ^
Also you have missed to put another <<
cout << "The name of the first found file is " << dataFile.cFileName << endl;`
// ^^
Also note that output formatting with std::ostream is different from printf() format string styles. Note I removed the %s from the above sample.
Change
const char path[] = "C:\\*.dmp"; // C-style string
hFind = FindFirstFile(path, &dataFile); // Pass the string directly

How can I use a string variable as a path url in C++

#include <iostream>
#include <windows.h>
#include <Lmcons.h>
#include <fstream>
using namespace std;
main(){
char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);
string cmd("C:\\Users\\");
cmd+=username;
cmd+=("\\AppData\\Roaming\\MiniApps");
}
Now I have complete path url in "cmd", and i want to use this variable as a path in c++ file handling . like
ofstream file;
file.open(cmd,ios::out|ios::app);
Open a file stream using ofstream, write the content and close.
#include<iostream>
#include <windows.h>
#include <Lmcons.h>
#include <fstream>
#include <string>
int main(){
char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);
std::string cmd("C:\\Users\\");
cmd+=username;
cmd+=("\\AppData\\Roaming\\MiniApps.txt");
std::ofstream file;
file.open (cmd.c_str(), std::ofstream::out | std::ofstream::app);
file << " Hello World";
file.close();
return 0;
}
With C++11 you can do
ofstream file(cmd,ios::app);
Without you have to do
ofstream file(cmd.c_str(),ios::app);