Why istream object after calling readsome() method don't give any chars in buffer? Is there any error in class construction?
StreamBuffer.h
#ifndef StreamBuffer_h
#define StreamBuffer_h
#include <string>
#include <fstream>
#include <iostream>
#include <iterator>
enum StreamBufferState
{
STREAMBUFFER_OK = 0,
STREAMBUFFER_EOF = 1
};
class StreamBuffer
{
std::fstream file;
std::istream istrm;
int maxBufferSize;
std::string buffer;
public:
StreamBuffer(int maxBuffSize, const std::string& filename);
~StreamBuffer();
void SetMaxBufferSize(unsigned int maxBuffSize);
StreamBufferState FullBufferWithData();
std::string GetDataBuffer();
};
#endif
StreamBuffer.cpp
#include "StreamBuffer.h"
using namespace std;
StreamBuffer::StreamBuffer(int maxBuffSize, const std::string& filename) : istrm( !filename.empty() ? file.rdbuf() : cin.rdbuf() )
{
SetMaxBufferSize(maxBuffSize);
if(!filename.empty())
{
file.open(filename.c_str(),ios::in | ios::binary);
}
else
{
std::cin>>noskipws;
}
}
StreamBuffer::~StreamBuffer()
{
file.close();
}
void StreamBuffer::SetMaxBufferSize(unsigned int maxBuffSize)
{
maxBufferSize = maxBuffSize;
}
StreamBufferState StreamBuffer::FullBufferWithData()
{
istrm.readsome((char*)&buffer[0],maxBufferSize);
if(istrm.eof())
return STREAMBUFFER_EOF;
return STREAMBUFFER_OK;
}
std::string StreamBuffer::GetDataBuffer()
{
string buf = buffer;
return buf;
}
File is opened, but readsome() don't read buffer.
You have undefined behavior in your code, as you try read into an empty string. You need to set the size of buffer.
An unrelated logical error: In the FullBufferWithData function you will return "OK" even if there is an error reading the file.
Related
I'm trying to display a simple map using the caca_put_str() / caca_printf() function except that it doesn't interpret the '\n' correctly. Any tips to share to fix this? The documentation is quite empty btw...
Thanks in advance !
Here is the code :
#include <string>
#include <caca.h>
#include <iostream>
#include <fstream>
caca_canvas_t *cv;
static std::string readFile(const std::string &file)
{
std::ifstream buffer(file);
std::string str;
if (buffer.is_open())
{
std::getline(buffer, str, '\0');
buffer.close();
return (str);
}
return (NULL);
}
int main(void)
{
std::string map = readFile("arcade.txt");
caca_display_t *dp;
caca_event_t event;
int width = 1080;
int height = 980;
cv = caca_create_canvas(width, height);
dp = caca_create_display(cv);
if (!dp)
std::exit(1);
caca_set_display_title(dp, "Windows");
while (true)
{
caca_refresh_display(dp);
caca_put_str(cv, 0, 0, map.c_str();
}
caca_free_canvas(cv);
caca_free_display(dp);
}
I'm trying to print this :
############################
#............##............#
#.####.#####.##.#####.####.#
#.####.#####.##.#####.####.#
#..........................#
#.####.##.########.##.####.#
#......##....##....##......#
######.#####.##.#####.######
#....#.##..........##.#....#
#....#.##.###--###.##.#....#
######.##.#......#.##.######
..........#......#..........
######.##.#......#.##.######
#....#.##.########.##.#....#
#....#.##..........##.#....#
######.##.########M##.######
#............##............#
#.####.#####.##.#####.####.#
#...##................##...#
###.##.##.########.##.##.###
#......##....##....##......#
#.##########.##.##########.#
But it is displayed on a single line.
First of all, this is NOT my own code! It's taken from Google's Android sourcecode https://android.googlesource.com/platform/art/+/android-9.0.0_r10/tools/hiddenapi/hiddenapi.cc
So, it should be tested and should work! But, it fails at the point "insert..."
Short code:
/*...*/
std::unordered_set<std::string> light_greylist_;
/*...*/
/*Caller:*/ OpenApiFile(light_greylist_path_, &light_greylist_);
bool OpenApiFile(const std::string& path, std::unordered_set<std::string>* list) {
std::ifstream api_file(path, std::ifstream::in);
for (std::string line; std::getline(api_file, line);) {
/* line IS filled; I've checked it with a simple fprintf(): [this IS my code for testing]*/
FILE *stream = fopen("test.txt", "a+");
fprintf(stream, "%s\n", line.c_str());
fclose(stream);
/* This is the point where it crashes with an "Illegal instruction (core dumped)"*/
list->insert(line);
}
api_file.close();
return true;
}
What goes wrong?
I'd make list a reference instead of a pointer. It's hard to say why the original code uses pointers since it'll most probably crash if called with NULL. Also check that the file has been successfully opened (even though it seems to have succeeded for you this time).
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <unordered_set>
bool OpenApiFile(const std::string& path, std::unordered_set<std::string>& list) {
std::ifstream api_file(path, std::ifstream::in);
if (!api_file) {
return false;
}
for (std::string line; std::getline(api_file, line);) {
list.insert(line);
}
return true;
}
int main(int argc, char* argv[]) {
std::vector<std::string> files(argv+1, argv+argc);
for(auto& light_greylist_path_ : files) {
std::unordered_set<std::string> light_greylist_;
if (OpenApiFile(light_greylist_path_, light_greylist_) == false) {
std::cerr << "failed opening "+light_greylist_path_+"\n";
} else {
for(auto& lg : light_greylist_) {
std::cout << lg << "\n";
}
}
}
return 0;
}
I am trying to use WritePrivateProfileString and GetPrivateProfileInt for a .ini parser.
When I put the code below into main(), or into a class constructor, it works for writing and reading.
But, when I make functions for writing and reading, and call the functions in main(), nothing happens, although the functions are run as they will cout something if I ask them to.
Here is the test program I wrote to demonstrate this:
#include <iostream>
#include <Windows.h>
#include <fstream>
#include <string>
#define CStringify(x) std::to_string(x).c_str()
int testvar = 12;
int returntestvar = 0;
std::fstream config;
std::string configstring = ".//config.ini";
int main()
{
WriteINI();
ReadINI();
std::cout << returntestvar << std::endl;
getchar();
}
void WriteINI()
{
config.open("config.ini", std::ios::app);
WritePrivateProfileString("Test", "Test1", CStringify(testvar), configstring.c_str());
}
void ReadINI()
{
config.open("config.ini", std::ios::app);
returntestvar = GetPrivateProfileInt("Test", "Test1", 0, configstring.c_str());
}
The above code creates and then edits an .ini file, as it is expected to.
However, if I move the code into a class, it will no longer work.
main.cpp
#include <iostream>
#include <Windows.h>
#include <fstream>
#include <string>
#include "INIClassTest.h"
extern INIParser* Parse;
int main()
{
Parse->WriteINI();
Parse->ReadINI();
std::cout << Parse->returntestvar << std::endl;
getchar();
}
INIClassTest.h
#pragma once
#include <fstream>
#include <string>
#include <Windows.h>
#define CStringify(x) std::to_string(x).c_str()
class INIParser
{
public:
INIParser();
void WriteINI();
void ReadINI();
int testvar;
int returntestvar;
std::fstream config;
std::string configstring;
};
extern INIParser* Parse;
INIClassTest.cpp
#include "INIClassTest.h"
#include <iostream>
INIParser* Parse = new INIParser();
INIParser::INIParser()
{
returntestvar = 0;
testvar = 18;
std::string configstring = ".//config.ini";
}
void INIParser::WriteINI()
{
config.open("config.ini", std::ios::app);
WritePrivateProfileString("Test", "Test1", CStringify(testvar), configstring.c_str());
}
void INIParser::ReadINI()
{
config.open("config.ini", std::ios::app);
returntestvar = GetPrivateProfileInt("Test", "Test1", 0, configstring.c_str());
}
The above code creates an .ini file, but it doesn't edit it or return anything.
You should NOT be using an fstream at all to create/open the INI file manually. WritePrivateProfileString() and GetPrivateProfileInt() handle that for you.
Also, if you read their documentation, you would see that you SHOULD NOT use a relative path for the INI file, or else the file will be relative to the Windows installation folder, not your app folder. So, you probably ARE reading/writing the INI file, just not where you are expecting from/to. If you want your INI file to be relative to your app's folder, you need to retrieve the path of your app's folder 1 and append the INI filename to it.
1: that is really not a good idea in general, though. Depending on where you install your app, the user might not have write access to that folder. You should instead use SHGetFolderPath() or SHGetKnownFolderPath() to get the user's local %AppData% folder, then create your own subfolder inside of it, and then create your INI file inside of that subfolder.
Try this instead:
#include <Windows.h>
#include <iostream>
#include <string>
#define CStringify(x) std::to_string(x).c_str()
std::string GetAppFolder();
std::string GetINIPath();
void WriteINI();
void ReadINI();
int testvar = 12;
int returntestvar = 0;
std::string configstring = GetINIPath();
int main()
{
WriteINI();
ReadINI();
std::cout << returntestvar << std::endl;
std::cin.get();
return 0;
}
std::string GetAppFolder()
{
char szFileName[MAX_PATH];
DWORD len = GetModuleFileName(NULL, szFileName, MAX_PATH);
std::string result(szFileName, len);
std::string::size_type pos = result.find_last_of("\\/");
result.resize(pos+1);
return result;
}
std::string GetINIPath()
{
return GetAppFolder() + "config.ini";
}
void WriteINI()
{
WritePrivateProfileString("Test", "Test1", CStringify(testvar), configstring.c_str());
}
void ReadINI()
{
returntestvar = GetPrivateProfileInt("Test", "Test1", 0, configstring.c_str());
}
The main reason your INIParser class fails is because your constructor is storing the INI file path in a local variable named configstring, instead of in the class's member also named configstring. Thus, the class member is blank when WriteINI() and ReadINI() are called.
Try this instead:
main.cpp
#include <iostream>
#include "INIClassTest.h"
int main()
{
Parse.WriteINI();
Parse.ReadINI();
std::cout << Parse.returntestvar << std::endl;
std::cin.get();
return 0;
}
INIClassTest.h
#pragma once
#include <string>
class INIParser
{
public:
INIParser();
void WriteINI();
void ReadINI();
int testvar;
int returntestvar;
std::string configstring;
};
extern INIParser Parse;
INIClassTest.cpp
#include <Windows.h>
#include "INIClassTest.h"
#include <string>
#define CStringify(x) std::to_string(x).c_str()
INIParser Parse;
static std::string GetAppFolder()
{
char szFileName[MAX_PATH];
DWORD len = GetModuleFileName(NULL, szFileName, MAX_PATH);
std::string result(szFileName, len);
std::string::size_type pos = result.find_last_of("\\/");
result.resize(pos+1);
return result;
}
static std::string GetINIPath()
{
return GetAppFolder() + "config.ini";
}
INIParser::INIParser()
{
returntestvar = 0;
testvar = 18;
configstring = GetINIPath();
}
void INIParser::WriteINI()
{
WritePrivateProfileString("Test", "Test1", CStringify(testvar), configstring.c_str());
}
void INIParser::ReadINI()
{
returntestvar = GetPrivateProfileInt("Test", "Test1", 0, configstring.c_str());
}
I want to make a program that reads the highest value from one file and stores it in another. I've read about ifstream and ofstream but how do I let the ofstream store the highest value from the instream in another file? Here is what I have so far:
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
struct CsvWhitespace : ctype<char> {
static const mask* make_table() {
static vector<mask> v{classic_table(), classic_table() + table_size};
v[','] |= space; // comma will be classified as whitespace
return v.data();
}
CsvWhitespace(size_t refs = 0) : ctype{make_table(), false, refs} {}
} csvWhitespace;
int main() {
string line;
ifstream myfile ("C:/Users/Username/Desktop/log.csv");
ofstream myfile2 ("C:/Users/Username/Desktop/log2.csv");
return 0;
}
auto v = vector<int>{};
myfile.imbue(locale{myfile.getloc(), &csvWhitespace});
copy(istream_iterator<int>{myfile}, istream_iterator<int>{}, back_inserter(v));
myfile2 << *max_element(begin(v), end(v));
}
Thanks in advance :)
You could just copy from the one file in the other, without having to worry about the format, by treating them in binary mode. Here is an example:
#include <stdio.h>
#include <string.h>
#define bufSize 1024
int main(int argc, char *argv[])
{
FILE *ifp, *ofp;
char buf[bufSize];
if (argc != 3)
{
fprintf(stderr,
"Usage: %s <soure-file> <target-file>\n", argv[0]);
return 1;
}
if ((ifp = fopen(argv[1], "rb")) == NULL)
{ /* Open source file. */
perror("fopen source-file");
return 1;
}
if ((ofp = fopen(argv[2], "wb")) == NULL)
{ /* Open target file. */
perror("fopen target-file");
return 1;
}
while (fgets(buf, sizeof(buf), ifp) != NULL)
{ /* While we don't reach the end of source. */
/* Read characters from source file to fill buffer. */
/* Write characters read to target file. */
fwrite(buf, sizeof(char), strlen(buf), ofp);
}
fclose(ifp);
fclose(ofp);
return 0;
}
which was given as an example in IP, source. You just need to specify the cmd arguments as the desired files.
You can do it like this. Live example using cin and cout rather than files.
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
struct CsvWhitespace : ctype<char> {
static const mask* make_table() {
static vector<mask> v{classic_table(), classic_table() + table_size};
v[','] |= space; // comma will be classified as whitespace
return v.data();
}
CsvWhitespace(size_t refs = 0) : ctype{make_table(), false, refs} {}
};
int main() {
string line;
ifstream myfile("log.csv");
ofstream myfile2("log2.csv");
auto v = vector<int>{};
myfile.imbue(locale{myfile.getloc(), new CsvWhitespace{}});
copy(istream_iterator<int>{myfile}, istream_iterator<int>{}, back_inserter(v));
myfile2 << *max_element(begin(v), end(v));
}
I have to write C++ program that like gzip can
*Take input from file or from char stream like compression below
gzip file
type file | gzip
*Program have file or char stream output like decompression below
gzip -d file.gz
gzip -dc file.gz
I don't know how to take to the task and what techniques have to use and how to create classes buffering input and output. I have classes buffering input and output and read/write data from/to file.
DataBuffer.h (taking uncompressed data from file):
#ifndef DataBuffer_h
#define DataBuffer_h
#include <fstream>
#include <string>
enum DataBufferState
{
DATABUFFER_OK = 0,
DATABUFFER_EOF = 1
};
class DataBuffer
{
std::fstream file;
std::string buffer;
unsigned int maxBufferSize;
public:
DataBuffer(const std::string& filename, unsigned int maxBuffSize);
~DataBuffer();
bool OpenFile(const std::string& filename);
void SetMaxBufferSize(unsigned int maxBuffSize);
DataBufferState FullBufferWithDataOld();
DataBufferState FullBufferWithData();
std::string GetDataBuffer();
};
#endif
DataBuffer.cpp:
#include "DataBuffer.h"
using namespace std;
DataBuffer::DataBuffer(const string& filename, unsigned int maxBuffSize)
{
OpenFile(filename);
SetMaxBufferSize(maxBuffSize);
}
DataBuffer::~DataBuffer()
{
file.close();
}
bool DataBuffer::OpenFile(const string& filename)
{
file.open(filename.c_str(),ios::in);
if(!file.is_open())
return false;
return true;
}
void DataBuffer::SetMaxBufferSize(unsigned int maxBuffSize)
{
maxBufferSize = maxBuffSize;
}
DataBufferState DataBuffer::FullBufferWithDataOld()
{
while(true)
{
string line;
streampos pos = file.tellg(); // Zapamietaj polozenie przed pobraniem linii
getline(file,line);
if( buffer.size()+line.size()>maxBufferSize )
{
// Cofnac wskaznik pliku
file.seekg(pos,ios::beg); // Przywroc polozenie sprzed pobrania linii
break;
}
buffer += line + "\n";
if(file.eof())
return DATABUFFER_EOF;
}
return DATABUFFER_OK;
}
DataBufferState DataBuffer::FullBufferWithData()
{
char c;
for(unsigned int i=0;i<maxBufferSize;++i)
{
c = file.get();
if(file.eof()) break;
buffer += c;
}
if(file.eof())
return DATABUFFER_EOF;
return DATABUFFER_OK;
}
string DataBuffer::GetDataBuffer()
{
string buf = buffer;
buffer.clear();
return buf;
}
BufferWriter.h (Save uncompressed data into file):
#ifndef BufferWriter_h
#define BufferWriter_h
#include <string>
#include <fstream>
class BufferWriter
{
std::string filename;
std::fstream file;
public:
BufferWriter(const std::string& filename_);
~BufferWriter();
bool OpenFile(const std::string& filename, bool appending);
void SendBufferToFile(std::string& buffer);
};
#endif
BufferWriter.cpp
#include "BufferWriter.h"
using namespace std;
BufferWriter::BufferWriter(const string& filename_)
{
filename = filename_;
OpenFile(filename.c_str(),false);
file.close();
}
BufferWriter::~BufferWriter()
{
file.close();
}
bool BufferWriter::OpenFile(const string& filename, bool appending)
{
if(appending)
file.open(filename.c_str(),ios::out | ios::app);
else
file.open(filename.c_str(),ios::out);
if(!file.is_open())
return false;
return true;
}
void BufferWriter::SendBufferToFile(string& buffer)
{
OpenFile(filename,true);
file.write(buffer.c_str(),buffer.size());
file.close();
}
Can you give me some hints how to improve code for input and output mechanisms?
Assume that I have class presented below, how to use istream or iterators to fill buffer with data from file or standard input. What classes from std or boost? What parameters? Somelike to support definition of class with this functionality.
[EDIT]:
#ifndef StreamBuffer_h
#define StreamBuffer_h
#include <string>
using namespace std;
enum DataBufferState
{
DATABUFFER_OK = 0,
DATABUFFER_EOF = 1
};
// gzip plik
// type plik | gzip -d
// gzip -d plik.gz
// gzip -dc plik.gz
// Parametr konstruktora to strumien z ktorego chcemy czytac i dlugosc bufora
class StreamBuffer
{
int maxBufferSize;
std::string buffer;
StreamBuffer(int maxBuffSize)
{
SetMaxBufferSize(maxBuffSize);
}
~StreamBuffer()
{
}
void SetMaxBufferSize(unsigned int maxBuffSize)
{
maxBufferSize = maxBuffSize;
}
DataBufferState FullBufferWithData()
{
// What to use what to do in this method to read part of file or standard char input to buffer?
}
std::string GetDataBuffer()
{
return buffer;
}
};
#endif
[EDIT2]:
I want to do the same thing as in this thread: Read from file or stdin, but in C++.
In general you read input from a source and write it to a sink. The simplest case is when you simply write what you read. You, however, want to apply a transformation (or filter) to the data that you read. Seeing as you're after "the c++ way," I'd suggest taking a look at boost::iostreams which abstracts the task in terms of sources/sinks.
Boost defines an abstract source by:
struct Source {
typedef char char_type;
typedef source_tag category;
std::streamsize read(char* s, std::streamsize n)
{
// Read up to n characters from the input
// sequence into the buffer s, returning
// the number of characters read, or -1
// to indicate end-of-sequence.
}
};
And sinks are defined in a similar way (with a write instead of a read, of course). The benefit of this is that the details of the source/sink is irrelevant - you can read/write to file, to a network adapter, or whatever, without any structural changes.
To apply filters I'd again suggest looking at boost::iostreams, although they do abstract a lot which somewhat complicates implementation..