I was uncertain whether or not the Windows API functions used the same kind of text/binary modes as the functions from the STL, just as i wrote in my original post. Sethjackson replies that there are no difference when using the API functions, and then you quote him saying he is wrong and that the functions from the STL does indeed differ between binary and text mode, that is kind of irrelevant, is it not? Anyways, not trying to put anyone off here.
When i've read the some of the file into my buffer the first time, will the file pointer be at the same place as the data that was last read? Or do i have to tell it in some way that i don't want it to jump to the beginning and read the same data again? Basically: Is there an equivalent of fseek?
Edit: Nvm, i just tried it out and it seems that the file pointer stays in it's place, hence no need for an fseek equivalent
Last edited by Neo1; 03-03-2008 at 02:11 PM.
How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.
If you do end up needing to seek:
SetFilePointer
SetFilePointerEx
Shrug. Let it be said, just as well...
Yep, as you see, the file point remains in place where the last read/write stopped.When i've read the some of the file into my buffer the first time, will the file pointer be at the same place as the data that was last read? Or do i have to tell it in some way that i don't want it to jump to the beginning and read the same data again? Basically: Is there an equivalent of fseek?
Edit: Nvm, i just tried it out and it seems that the file pointer stays in it's place, hence no need for an fseek equivalent
On a side note, the ReadFile documentation contains at least two errors I know of.
1) The conditions under which it returns are incomplete. In particular, there are two conditions not listed here:
a) End of file is reached. (NOT an error. The function returns FALSE on error.)
b) If the operation is asynchronous, the function returns immediately.
2) It claims the file must have been opened with GENERIC_READ access. Actually, FILE_READ_DATA suffices.
Note: #1 is definitely a documentation bug, since the documented behaviour doesn't make sense. #2 could be simply undocumented behaviour, so don't rely on FILE_READ_DATA being sufficient. MS could later add the requirement for FILE_READ_ATTRIBUTES or FILE_READ_EA to ReadFile and your program would break. However, one quite prominent blogger claims it's a bug, so I'll go with that.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
I have. Several months ago. I have never heard back, nor has the documentation been fixed.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
Ok, so i'm almost done now
(Notice how i'm not using exit() Elysia )Code:#include <windows.h> #include <iostream> #include <string> int main(int argc, char* argv[]) { if(argc != 3) { std::cerr << "Invalid number of arguments, " << "Correct usage is: split FILEPATH NUMBEROFOUTPUTFILES" << std::endl; return 1; } const unsigned int NumberOfOutputFiles = strtol(argv[2], NULL, 10); if(!NumberOfOutputFiles) { std::cerr << "Divison by 0!! BOOM the world just collapsed, try again..." << std::endl; return 1; } unsigned long OutputFileSize = 0; unsigned int i = 1; char *pBuffer = NULL; std::string OutputFileName; HANDLE hFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(!hFile) { std::cerr << "No such file." << std::endl; return 1; } unsigned long TotalFileSize = GetFileSize(hFile, NULL); OutputFileSize = TotalFileSize / NumberOfOutputFiles; pBuffer = new char[OutputFileSize]; std::cout << "File size is: " << TotalFileSize << " bytes." << std::endl; std::cout << "Splitting into " << NumberOfOutputFiles << " files - " << OutputFileSize << " bytes each." << std::endl; DWORD dwBytesRead, lpNumberOfBytesWritten; //Necessary to avoid Segfaults HANDLE OutputHandle; for(; i <= NumberOfOutputFiles; i++) { OutputFileName = "PART" + i; OutputFileName += argv[1]; ReadFile(hFile, pBuffer, OutputFileSize, &dwBytesRead, NULL); OutputHandle = CreateFile(OutputFileName.c_str(), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); WriteFile(OutputHandle, pBuffer, OutputFileSize, &lpNumberOfBytesWritten, NULL); } delete[] pBuffer; return 0; }
It's not working correctly though. First of all, the OutputFileName that i am generating in the for loop is not quite working as expected. If i call the program like this:
I get 3 output files, one of them called "ARTsoeasy.mp3" another one called "RTsoeasy.mp3", and the last one is just "Tsoeasy.mp3", what is wrong?split soeasy.mp3 3
Also, if i tell it to split the file into 4 or 5 pieces, it still only outputs the above 3 files?
Last edited by Neo1; 03-03-2008 at 02:54 PM. Reason: Typo
How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.
This shouldn't even compile, because it's plain wrong. Convert to string first, then add, otherwise it will probably do an implicit conversion to char and add - NOT what you want.
Also be careful about the size of each file. You're using integer division, which means you might actually loose some bytes there. So if it's a 2 MB file, you won't get even division.
I'd set the last output file size to (num_files - 1 * filepartsize) to make sure all bytes are copied.
How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.
You can't add an integer to the string directly.
I get a warning about an implicit conversion from int to char.Code:int n = 1000000; OutputFileName += n;
So what it does is convert your integer into a char and call operator += (char), which is bad.
So you need to convert that integer into a string first. Probably via stringstreams.
The
OutputFileName = "PART" + i; (+ i)
is bad because the result won't be what you expect.
I'm not sure what happens, but if you add i afterwards, you get an implicit conversion to a char.
Strange, i get no warnings, anyways, i'll fix it then
Also, could you elaborate abit on the integer division thing. I'm aware that division with an integer will result in some inaccuracy, but if i were to rewrite the last WriteFile call from
toCode:WriteFile(OutputHandle, pBuffer, OutputFileSize, &lpNumberOfBytesWritten, NULL);
I'd also have to increase the size of my buffer right?Code:WriteFile(OutputHandle, pBuffer, (NumberOfOutputFiles - 1 * OutputFileSize), &lpNumberOfBytesWritten, NULL);
Is this correct?Code:OutputFileSize = TotalFileSize / NumberOfOutputFiles; pBuffer = new char[NumberOfOutputFiles - 1 * OutputFileSize];
How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.
Well, it's because gcc does not have any narrowing warnings, unlike Visual Studio.
You would indeed have to increase the buffer... I think that looks about right.Also, could you elaborate abit on the integer division thing. I'm aware that division with an integer will result in some inaccuracy, but if i were to rewrite the last WriteFile call from
toCode:WriteFile(OutputHandle, pBuffer, OutputFileSize, &lpNumberOfBytesWritten, NULL);
I'd also have to increase the size of my buffer right?Code:WriteFile(OutputHandle, pBuffer, (NumberOfOutputFiles - 1 * OutputFileSize), &lpNumberOfBytesWritten, NULL);
Is this correct?Code:OutputFileSize = TotalFileSize / NumberOfOutputFiles; pBuffer = new char[NumberOfOutputFiles - 1 * OutputFileSize];
So this is how the code looks now:
It compiles with no warnings or errors, but whenever i run it i just get a message saying:Code:#include <windows.h> #include <iostream> #include <string> #include <sstream> int main(int argc, char* argv[]) { if(argc != 3) { std::cerr << "Invalid number of arguments, " << "Correct usage is: split FILEPATH NUMBEROFOUTPUTFILES" << std::endl; return 1; } const unsigned int NumberOfOutputFiles = strtol(argv[2], NULL, 10); if(!NumberOfOutputFiles) { std::cerr << "Divison by 0!! BOOM the world just collapsed, try again..." << std::endl; return 1; } unsigned long OutputFileSize = 0; unsigned int i = 1; char *pBuffer = NULL; std::string OutputFileName; HANDLE hFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(!hFile) { std::cerr << "No such file." << std::endl; return 1; } unsigned long TotalFileSize = GetFileSize(hFile, NULL); OutputFileSize = TotalFileSize / NumberOfOutputFiles; pBuffer = new char[NumberOfOutputFiles - 1 * OutputFileSize]; std::cout << "File size is: " << TotalFileSize << " bytes." << std::endl; std::cout << "Splitting into " << NumberOfOutputFiles << " files - " << OutputFileSize << " bytes each." << std::endl; DWORD dwBytesRead, lpNumberOfBytesWritten; //Necessary to avoid Segfaults HANDLE OutputHandle; std::stringstream ss (std::stringstream::in | std::stringstream::out); // Used for converting 'i' to a std::string for(; i <= NumberOfOutputFiles; i++) { ss << "PART" << i << argv[1]; OutputFileName = ss.str(); ReadFile(hFile, pBuffer, OutputFileSize, &dwBytesRead, NULL); OutputHandle = CreateFile(OutputFileName.c_str(), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(i == NumberOfOutputFiles) WriteFile(OutputHandle, pBuffer, (NumberOfOutputFiles - 1 * OutputFileSize), &lpNumberOfBytesWritten, NULL); else WriteFile(OutputHandle, pBuffer, OutputFileSize, &lpNumberOfBytesWritten, NULL); } delete[] pBuffer; return 0; }
The thing is though, i haven't yet gotten around to creating a support team yet :PThis application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Any idea what is wrong?
How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.