wofstream problem

cplusplus forum,

Windows 7, MS VS 2017, C++

I have a wstring that contains a unicode character and want to use it as a
file name.

wstring = filepath = L"C:\\testfile\x003A";

The debugger shows filepath as L"C:\\testfile:" which is what I expect.

wcout << filepath << endl;
displays C:\testfile: which is also what I expect.

I use it as a file name with this code:
wofstream woutfile;
woutfile.open(filepath);
woutfile.close();

There are no compiler errors and no run time messages but the file is never
opened?

What am I missing?

jerryd
0x3A is the colon character. Colons aren't valid filename characters in Windows.
Ganado,
Thanks for the reply.

I realize it's a colon but not the ascii code that windows rejects in a file name.
If all colon types are being rejected where is the run time error?

jerryd
I realize it's a colon but not the ascii code that windows rejects in a file name.
Print the value of each character of your filepath variable as an int. The value is simply 58 (0x3A). It being a wide character just makes it the equivalent of a short on Windows (16-bit).
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <fstream>

int main()
{
	std::wstring filepath = L"C:\\testfile\x003A";
	
	for (int i = 0; i < (int)filepath.length(); i++)
	{
		std::wcout << (int)filepath[i] << '\n';
	}
}

67
58
92
116
101
115
116
102
105
108
101
58


where is the run time error
I'm not sure what you mean. What kind of run-time error are you expecting? The standard library won't throw an exception here. You can check if the fstream is not in a usable state by doing:
1
2
3
4
5
woutfile.open(filepath);
if (!woutfile)
{
    std::cout << "error! cannot open file for writing!\n";
}


(And it's worth mentioning here, wofstream being able to take in a std::wstring is a Microsoft-only extension to the standard library.)
Last edited on
Ganado,

OK I'll try that code when I get back to this.

jerryd
C++17's <filesystem> library at first glance looks like it can deal with wide strings for filenames/paths.*
https://en.cppreference.com/w/cpp/filesystem/path/path

*I haven't used the library much beyond trying out the code samples, YMMV.
This program should output a more descriptive diagnostic for your original problem:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23506 for x64

#include <fstream>
#include <cstdio>
#include <cerrno>
#include <cassert>

#include <windows.h>

int main()
{
  wchar_t const* file_name = L"C:\\testfile\x003A";
    
  std::wprintf(L"attempting to open file name %s\n", file_name);  
  std::fflush(stdout);
  
  if (std::ofstream os{file_name})
    std::puts("success");
  else
  {
    // Here's what the C API has to say:
    std::perror("error");
      
    // Here's what the Windows API has to say:
    DWORD const last_error = GetLastError();
	DWORD const fmtflags = 
        FORMAT_MESSAGE_FROM_SYSTEM    | FORMAT_MESSAGE_IGNORE_INSERTS |
        FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_ALLOCATE_BUFFER;
    
    LPWSTR msg = nullptr;
	[[maybe_unused]] DWORD result = FormatMessageW(
        fmtflags,
		nullptr,
		last_error,
		0,
		(LPWSTR) &msg,
		0,
		nullptr);
      
     assert(result != 0);
      
     std::fwprintf(stderr, L"error: %s", msg);

     LocalFree(msg);
  }
}

It produces this output:
error: Invalid argument
error: The filename, directory name, or volume label syntax is incorrect.

For example, here:
https://rextester.com/TVHNZ96263
Last edited on
cplusplus forum,
I was able to find a way to create a windows file name with a colon. It's not an ascii
colon but Unicode colon. My goal was to put a time stamp at the end of the file name.

I was able to open the file with Notepad, Wordpad and LibreOffice, do some editing and
write the file back out with no complaints. I also opened it with Firefox, VS 2017 and
Internet Explorer, with no complaints. I don't have MS Office.

There are probably simpler ways to do it but this worked for me.

If you use my code as is you will probably have to create a folder named temp in C:\

jerryd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#define _CRT_SECURE_NO_DEPRECATE  // for VS 2017

#include <iostream>
#include <io.h>
#include <string>
#include <ctime>
#include <fstream>

using namespace std;

string month, day, hour, minute;

wstring wfilePath = L"C:\\temp\\testfile_";
wstring wmonth, wday, whour, wmin;
wstring colon = L"\xFF1A";

int main()
{
	time_t ttime = time(0);
	tm *local_time = localtime(&ttime);
	local_time->tm_mon = local_time->tm_mon + 1;
	if (local_time->tm_hour > 12) { local_time->tm_hour = local_time->tm_hour - 12; }

	// separate out the individual strings
	month = to_string(local_time->tm_mon);
	day =  to_string(local_time->tm_mday);
	hour = to_string(local_time->tm_hour);
	minute = to_string(local_time->tm_min);

	// convert them all to wstrings
	wstring wsMonth(month.begin(), month.end()); wmonth = wsMonth;
	wstring wsday(day.begin(), day.end()); wday = wsday;
	wstring wshour(hour.begin(), hour.end()); whour = wshour;
	wstring wsmin(minute.begin(), minute.end()); wmin = wsmin;

	// build the wfilePath
	wfilePath = wfilePath + wmonth + colon + wday + colon + whour + colon + wmin;

	ofstream file(wfilePath); // get a handle for the file
	file << "I'm a file with colons in my name" << endl;
	file.close();

	return 0;
}
Topic archived. No new replies allowed.