I'm using the following code to get machine local timezone:
time_t t = time(nullptr);
tm* local = localtime(&t);
std::ostringstream ss;
//ss.imbue(std::locale("C")); -> tried this, and also with ".UTF8"
ss << std::put_time(local, "%Z");
std::string timezone = ss.str();
On some locales I'm getting output with ANSI characters, such as for German machine the output timezone is: Mitteleuropäische Zeit
I don't find a way to disable ANSI characters in the output. I want to either get UTF-8 output (cross platform) or disable the ANSI characters and get something like Mitteleuropsche Zeit. I tried the imbue above (with either C or UTF8 locale), but same output.
Related
I am representing folder paths with boost::filesystem::path which is a wstring on windows OS and I would like to convert it to std::string with the following method:
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> conv1;
shared_dir = conv1.to_bytes(temp.wstring());
but unfortunatelly the result of the following text is this:
"c:\git\myproject\bin\árvíztűrőtükörfúrógép" ->
"c:\git\myproject\bin\árvÃztűrÅ‘tükörfúrógép"
What do I do wrong?
#include <string>
#include <locale>
#include <codecvt>
int main()
{
// wide character data
std::wstring wstr = L"árvíztűrőtükörfúrógép";
// wide to UTF-8
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv1;
std::string str = conv1.to_bytes(wstr);
}
I was checking the value of the variable in visual studio debug mode.
The code is fine.
You're taking a wstring that stores UTF-16 encoded data, and creating a string that stores UTF-8 encoded data.
I was checking the value of the variable in visual studio debug mode.
Visual Studio's debugger has no idea that your string stores UTF-8. A string just contains bytes. Only you (and people reading your documentation!) know that you put UTF-8 data inside it. You could have put something else inside it.
So, in the absence of anything more sensible to do, the debugger just renders the string as ASCII*. What you're seeing is the ASCII* representation of the bytes in your string.
Nothing is wrong here.
If you were to output the string like std::cout << str, and if you were running the program in a command line window set to UTF-8, you'd get your expected result. Furthermore, if you inspect the individual bytes in your string, you'll see that they are encoded correctly and hold your desired values.
You can push the IDE to decode the string as UTF-8, though, on an as-needed basis: in the Watch window type str,s8; or, in the Command window, type ? &str[0],s8. These techniques are explored by Giovanni Dicanio in his article "What's Wrong with My UTF-8 Strings in Visual Studio?".
It's not even really ASCII; it'll be some 8-bit encoding decided by your system, most likely the code page Windows-1252 given the platform. ASCII only defines the lower 7 bits. Historically, the various 8-bit code pages have been colloquially (if incorrectly) called "extended ASCII" in various settings. But the point is that the multi-byte nature of the data is not at all considered by the component rendering the string to your screen, let alone specifically its UTF-8-ness.
I use boost.log to create multi log file according to string value. But when the string is UTF8 coded, the file created has incorrect name (like this: è°.æ¦ç).
BOOST_LOG_SCOPED_LOGGER_ATTR(Logger::motion_checker, "RoleName", boost::log::attributes::constant< std::string >(name))
typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::text_multifile_backend> multifile_sink;
boost::shared_ptr<multifile_sink> sink(new multifile_sink);
sink->locked_backend()->set_file_name_composer(boost::log::sinks::file::as_file_name_composer(
boost::log::expressions::stream << "./log/MotionCheck/" << boost::log::expressions::attr< std::string >("RoleName") << ".log"));
sink->set_formatter
(
boost::log::expressions::format("[%1%] - %2%")
% boost::log::expressions::attr< boost::posix_time::ptime >("TimeStamp")
% boost::log::expressions::smessage
);
sink->set_filter(channel == motion_check_channel);
core->add_sink(sink);
How to let boost.log handle UTF8 file name?
Boost.Log composes the file name in the encoding that is native for the underlying operating system. On Windows the file name is a UTF-16 string (the character type is wchar_t), on most POSIX systems it is typically UTF-8 (the character type is char).
In order to produce the file name in the native encoding the as_file_name_composer adapter creates a stream that performs character code conversion as needed when the adapted formatter is invoked. This basically lets you use both narrow and wide strings in the formatter as long as the encoding can be converted to the native one. You have to know though that the same-typed strings are assumed to have the same encoding, so if the native multibyte encoding is UTF-8 then all your narrow strings must also be UTF-8.
When character code conversion happens, the stream uses a locale that you can provide as the second argument for as_file_name_composer. By default the locale is default-constructed. If your default-constructed locale is not UTF-8 then the conversion will produce incorrect result, which I think is what's happening. You have to either set up your global locale to be UTF-8 or create a UTF-8 locale and pass it to the as_file_name_composer adapter. You can use Boost.Locale to generate a UTF-8 locale easily.
I am trying to get the unicode character macron (U+00AF), i.e., an overscore, to print consistently on various linux consoles. So far, some consoles work (e.g., putty ssh), others do not (e.g., ubuntu shell), and I have not been able to figure out what I am doing right in one case (probably luck) and wrong in the other.
I do know the basics of Unicode and Utf8, but I have not been able to figure out how to consistently get consoles to display the appropriate characters.
Any suggestions? Note that this is explicitly for unix consoles - all of the similar questions I have found focused on Windows-specific console commands.
Here is what I would effectively like to get working:
wchar_t post = L'¯'; //0xC2AF
std::wcout << post << std::endl;
Unfortunately nothing I tried or could find in the way of suggestions consistently displayed the appropriate character, so I ended up using an ASCII hyphen '-' as a close enough match.
The solution is to put it into stream as a multicharacter string:
std::string s = "\uC2AF";
std::cout << s << std::endl;
or to set a locale using
char* setlocale( int category, const char* locale);
function:
std::locale old_locale; // current locale
setlocale(LC_ALL, "en_US.UTF-8");
wchar_t w = 0xC2AF;
std::wcout << w << std::endl;
setlocale(LC_ALL, old_locale.name().c_str()); // restore locale
The final result is however dependent on many user settings (console, fonts, etc.), so there is no guarantee that it will be OK.
I want to format a date and time as a string using the format:
20130630-03:11:45.862
I can do most of this by using strftime, however there is no clear way to achieve fractional seconds on the end.
My current code is:
time_t rawtime;
time(&rawtime);
tm* timeinfo = localtime(&rawtime);
char buffer[80];
strftime(buffer, 80, "%G%m%d-%I:%M:%S", timeinfo);
This produces the value without the fractional seconds part.
However ultimately I just want to have a string version of the date in this format, and don't care what API it takes.
I'm using g++ on Linux in case it's relevant.
If you don't care about the API, you could use boost::date_time and it's time_facet.
Short example so far:
// setup facet and zone
// this facet should result like your desired format
std::string facet="%Y%m%d-%H:%M:%s";
std::string zone="UTC+00";
// create a facet
boost::local_time::local_time_facet *time_facet;
time_facet = new boost::local_time::local_time_facet;
// create a stream and imbue the facet
std::stringstream stream(std::stringstream::in | std::stringstream::out);
stream.imbue(std::locale(stream.getloc(), time_facet));
// create zone
boost::local_time::time_zone_ptr time_zone;
time_zone.reset(new boost::local_time::posix_time_zone(zone));
// write local from calculated zone in the given facet to stream
stream << boost::local_time::local_microsec_clock::local_time(time_zone);
// now you can get the string from stream
std::string my_time = stream.str();
This example is maybe incomplete, because I copied some code out of mine, but I hope you got the point.
With the facet, you can setup your format. The %s (small s with, big S without fractial) setup seconds with fractial. You can read this in the documentation facet format.
The timezone is for calculating your local machine time to the right zone.
In C++, I would like to save hexadecimal string into file as unicode character
Ex: 0x4E3B save to file ---> 主
Any suggestions or ideas are appreciated.
What encoding? I assume UTF-8.
What platform?
If you under Linux then
std::locale loc("en_US.UTF-8"); // or "" for system default
std::wofstream file;
file.imbue(loc); // make the UTF-8 locale for the stream as default
file.open("file.txt");
wchar_t cp = 0x4E3B;
file << cp;
However if you need Windows it is quite different story:
You need to convert code point to UTF-8. Many ways. If it is bigger then 0xFFFF then convert it to UTF-16 and then search how to use WideCharToMultiByte, and then save to file.