i am trying to open a file handler to a path i got from file,
i have input file which has a full path in it for example :
c:\def\es1.txt
i replaced the "\" char to double "\" so it will fit string format and then i am using :
myfile = fopen("temp.txt", "r");
while (fgets(line, line_size, myfile) != NULL){
printf("==============================\n");
printf(line);
system("PAUSE\n");
mbstowcs(wtext, line, strlen(line) + 1);//Plus null
_tprintf(wtext);
LPWSTR ptr = wtext;
hFile = CreateFile(wtext, // name of the write
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // default security
OPEN_EXISTING, // create new file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
if (hFile == INVALID_HANDLE_VALUE)
{
DisplayError(TEXT("CreateFile"));
_tprintf(TEXT("Terminal failure: Unable to open file \"%s\" for write.\n"), wtext);
return;
}
else {
printf("yes!!!!!!!\n");
}
when the command _tprintf(wtext); occurs i see the string as it should be:
"c:\def\es1.txt"
but the CreateFile command fails:
FATAL ERROR: Unable to output error code.
ERROR: CreateFile failed with error code 123 as follows:
The filename, directory name, or volume label syntax is incorrect.
Terminal failure: Unable to open file "c:\\def\\es1.txt
" for write.
when i replace the wtext variable in CreateFile with :L"c:\\def\\es1.txt"
it works fine, what is the problem?
Are you sure that your file which contains the path doesn't contains any special char at the end ? Like a \r or \n ?
You can print the strlen and know if your string contains only classic char.
I replaced the "\" char to double "\" so it will fit string format
A backslash in a string is a backslash. That they must be escaped in string literals doesn't mean they must be doubled in every string you process. In other words, "\\" is a string literal containing exactly one backslash.
A file named c:\\def\\es1.txt with double-backslashes doesn't seem to exist, so opening fails. At least that's what I'm guessing. I'm not familiar with Windows; under Linux, double-slashes in file names are interpreted as one slash.
Thank you all, it was the newline and the need to clear the char var:
while (fgets(line, line_size, myfile) != NULL){
printf("==============================\n");
printf(line);
//solution
char deststring[BUFFER];
memset(deststring, '\0', sizeof deststring);
strncpy(deststring, line, strlen(line) - 1);
mbstowcs(wtext, deststring, strlen(deststring) + 1);//Plus null
_tprintf(wtext);
Related
So I am using the open function in C to open a target file, and if it does not exist, I will create it. I am redirecting stdout from the terminal into this file. When I run my program, it creates a new file with the name that I type into the shell, but appends a "?" to the end. Can someone help me figure out how to remove that?
My code is below
// Take output from ls as input into the next argument.
command = strtok(NULL, " "); // Holds the value for the destination file.
printf("%s\n", command);
int targetFD = open(command, O_WRONLY | O_CREAT | O_TRUNC, 0700);
if (targetFD == -1)
{
perror("open()");
exit(1);
}
printf("The file descriptor for targetFD is %d\n", targetFD);
int result = dup2(targetFD, 1);
if (result == -1)
{
perror("dup2");
exit(2);
}
ls(); // instead of printing ls to the terminal, it gets written to the file.
Here is an image of a sample execution. Notice how junk.txt file already exists...I want my program to redirect "ls" into that file or create a new one of the file does not exist.
sample program execution
I bet the ? is not a literal ? character, but the way that your version of ls displays a filename containing a non-printable character, e.g. if you use GNU ls and have the -q option enabled by default.
I also note that in your sample output, there is an extra blank line between junk.txt and The file descriptor for targetFD. You only printed one newline after command, so I suspect that the string command itself ends with a \n. That would fit if it was parsed from a string that ended with \n (e.g. a line read with fgets). So you actually created a file named junk.txt\n, and ls prints the newline character as ?.
Perhaps you wanted to use " \n" as the delimiter string for strtok, so that a newline will also be treated as a delimiter and not be included in the token string.
I am trying to create a file with GENERIC_WRITE permission with a path entered by the user.
To get user input, I am using fwgets function.
VOID DoCreateFile() {
SIZE_T sAlloc = sizeof(WCHAR) * (MAX_WPATH + 1); // allocation size
// allocating space and checking if actually allocated
LPWSTR lpPath = (LPWSTR)malloc(sAlloc);
LPWSTR lpContent = (LPWSTR)malloc(sAlloc);
if (lpPath == NULL || lpContent == NULL) {
PrintLastError(L"malloc()", TRUE);
}
wprintf(L"Enter path of file: ");
fgetws(lpPath, sAlloc, stdin); // read the contents of stdin with space
wprintf(L"Enter content (max 256 chars): ");
fgetws(lpContent, sAlloc, stdin);
/*
Documentation: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
*/
HANDLE hFile = CreateFileW(lpPath, // path of file
GENERIC_WRITE, // creating file with write permission
FILE_SHARE_READ, // allow other process to open file for reading
NULL, // disallow handle inheritance
CREATE_ALWAYS, // overwrite file if exists, otherwise create a new one
FILE_ATTRIBUTE_NORMAL, // do not set any file attributes
NULL // not using any file template
);
if (hFile == INVALID_HANDLE_VALUE) {
PrintLastError(L"CreateFileW()", TRUE);
}
CloseHandle(hFile);
}
Error message printed by PrintLastError function: CreateFileW() Failed! The filename, directory name, or volume label syntax is incorrect.
The input I have entered on the console is
Enter path of file: c:\file.txt
Enter content (max 256 chars): s
I have also tried file path \\.\C:\file.txt.
FYI, when I replace lpPath with a wide string literal L"C:\\Files.txt", the function succeeds.
This function is passed the path of a text file(mapper_path) which contains paths to other text files on each line. I am supposed to open the mapper_path.txt file, then open and evaluate each of the paths within it (example in output).
fopen succeeds on the mapper_path file but fails on the paths which it contains.
In the failure condition, it prints the EXACT path I'm trying to open.
I'm working in C on windows and running commands on Ubuntu subsystem.
How can I properly read and store the sub-path into a variable to open it?
SOLVED with Rici's suggestion!
int processText(char * mapper_path, tuple * letters[])
{
char line[LINE_SIZE];
char txt_path[MAX_PATH];
FILE * mapper_fp = fopen(mapper_path, "r");
if(!mapper_fp)
{
printf("Failed to open mapper path: %s \n", mapper_path);
return -1;
}
//!!! PROBLEM IS HERE !!!
while(fgets(txt_path, MAX_PATH, mapper_fp))
{
//remove newline character from end
txt_path[strlen(txt_path)-1] = 0;
//open each txt file path, return -1 if it fails
FILE* fp = fopen(txt_path, "r");
if(!fp)
{
printf("Failed to open file path:%s\n", txt_path);
return -1;
}
//...more unimportant code
prints:
Failed to open filepath:
/mnt/c/users/adam/documents/csci_4061/projects/blackbeards/testtext.txt
This is the exact path of the file i am trying to open.
I suspect that the problem is related to this:
I'm working in C on windows and running commands on Ubuntu subsystem.
Presumably, you created the mapper.txt file using Windows tools, so it has Windows line endings. However, I think the Ubuntu subsystem does not know about Windows line endings, and so even though you open the file in mode 'r', it does not translate CR-LF into a single \n. When you then remove the \n at the end of the input, you still leave the \r.
That \r won't be visible when you print out the line, since all it does is move the cursor to the beginning of the line and the next character output is a \n. It's usually a good idea to surround strings with other text when you print debugging messages, since that can give you a clue about this sort of problem. If you'd used:
printf("Failed to open file path: '%s'\n", txt_path);
you might have seen the error:
'ailed to open filepath: '/mnt/c/users/adam/documents/csci_4061/projects/blackbeards/testtext.txt
Here, the hint that there is a \r at the end of the string is the overwriting of the first character of the message with the trailing apostrophe.
It's not quite accurate to say that fgets "adds a \n character to the end [of the line read]." It's more accurate to say that it doesn't remove that character, if it is present. It is quite possible that there isn't a newline at the end of the line. The line may be the last line in a text file which doesn't end with a newline character, for example. Or the fgets might have been terminated by reaching the character limit you supplied, rather than by finding a newline character.
So you are certainly better off using the getline interface, which has two advantages: (a) it allocates storage for the line itself, so you don't need to guess a maximum length in advance, and (b) it tells you exactly how many characters it read, so you don't have to count them.
Using that information, you can then remove a \n which happens to be at the end of the line, if there is one, and then remove the preceding \r, if there is one:
char* line = NULL;
size_t n_line = 0;
for (;;) {
ssize_t n_read = getline(&line, &n_line, mapper_fp);
if (n_read < 0) break; /* EOF or some kind of read error */
if (n_read > 0 && line[n_read - 1] == '\n')
line[nread--] = 0;
if (n_read > 0 && line[n_read - 1] == '\r')
line[nread--] = 0;
if (nread == 0) continue; /* blank line */
/* Handle the line read */
}
if (ferr(mapper_fp))
perror("Error reading mapper file");
free(line);
I'm writing an application which should read some data at some level from a file. When I run the code (including fopen() and fclose())for more than a few hundred times, I got the error message (which I know it means that it cannot open the file):
Debug Assertaion Failed!
Program:
D:\blahblah
file: f:\dd\vctools\crt\crtwin32\stdio\fgets.c
Line: 57
Expression: (string!=NULL)
Can you please help me to understand why it should break after more than three hundered time?
Func_Main(char * filePath, ...){
for(int i=0;i<1000;i++){
Func_1(filePath);
....
}
....
}
Func_1(char* filepath){
char buffer[1024];
FILE * file= NULL;
file = fopen(filepath, "r");
while(fgets(buffer, sizeof(buffer), file)){
\\ do something
}
fclose(file);
}
You should check the return value of fopen. It will return a null pointer if opening the file failed.
And it will fail because \ is an escape character , use \\ in the filename string.
Problems I see:
You never use the argument passed to Func_1. You use a hard coded path instead.
The hard coded path has an error. You are not escaping the backslash in the hard coded path . It should be:
file = fopen("c:\\blahblah.txt", "r");
^^
You are not checking whether fopen was successful. You are assuming it was successful. Use:
file = fopen("c:\\blahblah.txt", "r");
if ( file == NULL )
{
// Deal with the error.
perror("Unable to open the file");
}
Update, after the OP edited the question
The first two points can be ignored. The last point still needs to be considered.
file = fopen(filepath, "r");
if ( file == NULL )
{
// Deal with the error.
perror("Unable to open the file");
}
I work on Xcode and I have a simple function that opens a file using open in C.
void mfs_workwith() {
char *token, *temp_token;
char *search = ".";
temp_token = (char*)malloc(sizeof(char)*strlen(cc[1]));
strcpy(temp_token, cc[1]);
if ((token = strtok(temp_token, search)) == NULL) {
printf("mfs_workwith command is only used with mfs type files e.g. example.mfs \n");
} else if ((token = strtok(NULL, " \n\0")) == NULL) {
printf("mfs_workwith command is only used with mfs type files e.g. example.mfs \n");
} else if (strcmp(token, "mfs") == 0) {
filename = malloc(sizeof(char)*strlen(cc[1]));
strcpy(filename, cc[1]);
if ((file_mfs = open(filename, O_RDWR)) == -1) {
perror("open error");
} else {
printf("open successful \n");
}
}
}
The name of the file is stored in a global array and then copied into local buffers in order to tokenize and check if it has the right format (.mfs).
Then if everything is ok I make a fresh copy of the name of the file and call open with it.
My problem is that when I run my program in terminal it runs fine, prints open successful and then continues. But when I try to run it in Xcode it fails with this error:
No such file or directory
I am giving the input file.mfs which is the name of a file in the same directory.
Am I missing something obvious?
I found the problem thanks to iharob's comment. It seems xcode has a hard time opening relative paths since it uses a different file while running the program. There is a relative discussion here:
Open method opens files with full path only C++
thanks again everyone.
This:
filename = malloc(sizeof(char)*strlen(cc[1]));
strcpy(filename, cc[1]);
is broken, it fails to allocate room for the string's terminator, so it causes buffer overflow and undefined behavior.
Also, you never need to scale by sizeof (char), that's always 1. It should be:
filename = malloc(strlen(cc[1]) + 1);
strpcy(filename, cc[1]);
or, if you have it, just:
filename = strdup(cc[1]);