I have the following c++ code in visual studio to read characters from a file.
ifstream infile;
infile.open(argv[1]);
if (infile.fail()) {
cout << "Error reading from file: " << strerror(errno) << endl;
cout << argv[0] << endl;
}
else {
char currentChar;
while (infile.get(currentChar)) {
cout << currentChar << " " << int(currentChar) << endl;
//... do something with currentChar
}
ofstream outfile("output.txt");
outfile << /* output some text based on currentChar */;
}
infile.close();
The file in this case is expected to contain mostly normal ASCII characters, with the exception of two: “ and ”.
The problem is that the code in it's current form is not able to recognise those characters. couting the character outputs garbage, and its int conversion yields a negative number that's different depending on where in the file it occurs.
I have a hunch that the problem is encoding, so I've tried to imbue infile based on some examples on the internet, but I haven't seemed to get it right. infile.get either fails when reaching the quote character, or the problem remains. What details am I missing?
The file you are trying to read is likely UTF-8 encoded. The reason most characters read fine is because UTF-8 is backwards compatible with ASCII.
In order to read a UTF-8 file I'll refer you to this: http://en.cppreference.com/w/cpp/locale/codecvt_utf8
#include <fstream>
#include <iostream>
#include <string>
#include <locale>
#include <codecvt>
...
// Write file in UTF-8
std::wofstream wof;
wof.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t,0x10ffff,std::generate_header>));
wof.open(L"file.txt");
wof << L"This is a test.";
wof << L"This is another test.";
wof << L"\nThis is the final test.\n";
wof.close();
// Read file in UTF-8
std::wifstream wif(L"file.txt");
wif.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t,0x10ffff, std::consume_header>));
std::wstringstream wss;
wss << wif.rdbuf();
(from here)
try:
while (infile.get(¤tChar, 1))
Also, be sure that you pass argv[1]. Print its value:
cout<<argv[1]<<endl;
Related
i'm trying to show in the console a cinese text, it has been pasted from wikipedia in a .txt file (i don't know the codification, maybe UTF-8?)
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
#include <locale>
#include <codecvt>
using namespace std;
int main () {
const locale utf8_locale
= locale(locale(), new std::codecvt_utf8<wchar_t>());
std::wifstream file("dao.txt");
file.imbue(utf8_locale);
wstring s;
if (file.is_open())
{
while (getline(file, s))
{
cout << s << '\n';
// Do something with the string
}
else cout << "Unable to open file";
myfile.close();
}
return 0;
}
I receive:
error: no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream}' and 'std::__cxx11::wstring {aka std::__cxx11::basic_string}')|
Why does << is not overloaded?
There are a couple of errors:
Else does not match if
if (file.is_open())
{
...
else cout << "Unable to open file";
...
}
Use std::wcout. s is a wide string. Use the wide output.
std::wcout << s << '\n'; // not std::cout notice the w
No variable called myfile I probably meant file
/*my*/file.close();
Note:
You have to imbue the stream before opening it.
std::wifstream file;
file.imbue(utf8_locale);
file.open("dao.txt");
The problem is that an imbue will fail if any characters have been read from the file. Some implementations will check to see if there is a BOM marker (putting the chars back if there are none). But checking these BOM characters means the file has been read and thus will make the imbue fail. So always imbue the file before opening.
Note: I am using the C++11 standard, so I don't see why this isn't working with or without c_str() appended.
I have the following code:
// open streams
ifstream in(input);
ofstream out(output);
// get which file to open
in.ignore(INT_MAX, ':'); // we don't need the beginning part
in.ignore(); // remove trailing whitespace
string fileLocation;
getline(in, fileLocation);
out << "Loading: " << fileLocation << endl;
cout << "Loading: " << fileLocation << endl;
// now that we know where the file is, load it:
ifstream file(fileLocation);
which reads from a file that looks vaguely like this
File: file.txt
(Subcommands below)
I know that I am pulling the correct filename because of the terminal output.
Anyway, I noticed that the stream wasn't opening properly, so I added this conditional to check:
if ( !file )
{
cout << "File wasn't loaded properly." << endl;
}
And sure enough, I see that message when running the program.
My question is this: how come, when I hard-code the file location, e.g. ifstream file("file.txt") it opens up no problem? How do I get this working properly?
I want to read out the chrome history from its file. I want to get all characters and null byte that's in that file. The problem I'm facing is that I only get some part of the text that's in the file. I belive it stop due to a null byte or a speical character.
Here´s my code that I have at the moment.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
int main(){
string str;
std::ifstream in("c:/Users/Petrus/Documents/History"); // I have copy my file into my documents to make sure I'm not interfering with Chrome.
std::stringstream buffer;
if (!in.is_open()){
cout << "Failed to open" << endl;
}
else{
cout << "Opened OK" << endl;
}
buffer << in.rdbuf();
std::string contents(buffer.str());
while (getline(buffer, str))
{
cout << str;
}
in.close();
system("PAUSE");
return 0;
}
If you want to take a look at the chrome history file its located at:
C:\Users\YOUR NAME\AppData\Local\Google\Chrome\User Data\Default -->History
(PS You have to include hidden files to be able to see Appdata.)
Thanks in advance
std::getline() should be used only to read plain text files.
To read arbitrary binary files you should use read(). Additionally, on your operating system you must open binary files using the std::ios::binary flag.
I am trying to design a program that will open any text file, read it into a string, encrypt the string with XOR, and write the string to a new text file. The code below works, but generates multiple "system beeps".
My wild guess is that I am not handling whitespaces correctly? I'm not sure. Any ideas what I'm doing wrong?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream inFile;
ofstream outFile;
// Define variables
string fileName,
key = "seacrest out";
// Input
cout << "Please enter the name of the file you wish to encrypt: ";
cin >> fileName;
cout << endl;
inFile.open(fileName, ios::in | ios::binary);
string str((istreambuf_iterator<char>(inFile)), istreambuf_iterator<char>()); // Reads a text file into a single string.
inFile.close();
cout << "The file has been read into memory as follows:" << endl;
cout << str << endl;
system("pause");
// Encryption
cout << "The file has been encrypted as follows:" << endl;
for (unsigned x = 0; x < str.size(); x++) // Steps through the characters of the string.
str[x] ^= key[x % key.size()]; // Cycles through a multi-character encryption key, and encrypts the character using an XOR bitwise encryption.
cout << str << endl; // This code works, but I get system beeps. Something is still wrong.
// Write Encrypted File
cout << "Please enter the file name to save the encrypted file under: ";
cin >> fileName;
cout << endl;
outFile.open(fileName, ios::out | ios::binary);
outFile.write(str.c_str(), str.size()); // Writes the string to the binary file by first converting it to a C-String using the .c_str member function.
system("pause");
return 0;
}
those beep sounds you heard are bytes equal to 0x07 in your file. you can get rid of this problem simply by not printing the contents of a binary file in the console.
kudos for trying to do it yourself.
the problem is you are not handling some characters carefully for eg white spaces may try to print out
char d=(char)(7);
printf("%c\n",d);
which is called a bell character.
here is an easy implementation for XOR encryption but i recommend to write your own version
http://programmingconsole.blogspot.in/2013/10/xor-encryption-for-alphabets.html
When you xor bytes with some random key, you're going to get some unusual byte sequences. These byte sequences happen to correspond to some unprintable characters that you can use to make the console beep by sending them to the console.
If you remove the line
cout << str << endl;
You'll find that your console won't beep any more since you're not printing the erroneous byte sequences that the console is interpreting as commands to beep.
If your console is set to ASCII mode (which I assume it is since you have system("PAUSE") which indicates you're on Windows where the console is not Unicode unless you set it explicitly IIRC) then those unprintable characters are all bytes less than 0x1F and the byte 0x7F, and the character that causes the console to beep is 0x7 (called "bell").
tl;dr
You get some 0x7 bytes in your encrypted data that cause the console to beep when printed. Remove cout << str << endl; to fix it.
I'm using Qt/C++ on a Linux system. I need to convert a QLineEdit's text to std::wstring and write it into a std::wofstream. It works correctly for ascii strings, but when I enter any other character (Arabic or Uzbek) there is nothing written in the file. (size of file is 0 bytes).
this is my code:
wofstream customersFile;
customersFile.open("./customers.txt");
std::wstring ws = lne_address_customer->text().toStdWString();
customersFile << ws << ws.length() << std::endl;
Output for John Smith entered in the line edit is John Smith10. but for unicode strings, nothing.
First I thought that is a problem with QString::toStdWString(), but customersFile << ws.length(); writes correct length of all strings. So I guess I'm doing something wrong wrong with writing wstring in file. [?]
EDIT:
I write it again in eclipse. and compiled it with g++4.5. result is same:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
cout << "" << endl; // prints
wstring ws = L"سلام"; // this is an Arabic "Hello"
wofstream wf("new.txt");
if (!wf.bad())
wf << ws;
else
cerr << "some problem";
return 0;
}
Add
#include <locale>
and at the start of main,
std::locale::global(std::locale(""));