How to find the file pointer position in c++? - c++

I am currently working with files in c++ and I want to read a file after a certain position. I read online that you can't open a file to read and write simultaneously. Is there a way to return the position of the file pointer at a certain moment and use it to extract the information after it?

What you read was wrong.
#include <fstream>
#include <string>
int main()
{
std::fstream file("test.txt", std::ios::in | std::ios::out | std::ios::binary);
std::string s;
file >> s;
// get current read position
auto read_pos = file.tellg();
// set current write position
file.seekp(read_pos, std::ios::beg);
static const char data[] = "aaa";
// write some data
file.write(data, 3);
}

Related

C++ fstream writes garbage to file

The code below creates a vector that contains a vector of chars. It opens a fstream to a file. and then write the first char from the first vector. I tried to methods to write the char. Finally, I tried open a new 'fstream' and from it to print what I wrote. Both the printing and a simple inspection of the file shows it contian nothing, or sometimes garbage (dependening on the order of the writes). No errors or any weried output appear. I'm really loosing my mind over this.
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
int main()
{
std::vector<char> y(6, 0);
y[0] = 1;
std::vector<std::vector<char>> vy;
vy.push_back(y);
std::fstream dateir("ffff.dat", std::ios::out | std::ios::out | std::ios::binary);
dateir<<vy[0][0] << endl;
int temp = vy[0][0];
dateir.write((char *)&temp, sizeof(int));
dateir.close();
cout << "here" << endl;
std::ifstream dateir2("ffff.dat", std::ios::out | std::ios::out | std::ios::binary);
if (dateir2.is_open())
{
std::cout << dateir2.rdbuf();
}
else{
cout << "no";
}
dateir2.close();
cout << "end";
return 0;
}
You have...a number of problems here.
std::fstream dateir("ffff.dat", std::ios::out | std::ios::out | std::ios::binary);
Is there a reason you've specified std::ios::out | std::ios::out? It's harmless, but clearly redundant.
As a first stab at things, I'd simplify the code a bit:
std::ofstream out("ffff.dat", std::ios::binary);
int data = 1;
out.write((char *)&data, sizeof(data));
out.close();
std::ifstream in("ffff.dat", std::ios::binary);
int data2;
in.read((char *)&data2, sizeof(data2));
if (data == data2) {
// what we read matched what we wrote
} else {
// what we read didn't match what we wrote
}
When you write binary data to a file, you usually want to just read it back in the way you wrote it out. If you want to look at the individual characters, you can do that but to get something that's semi-readable, you probably want to print them out in hexadecimal, or something on that order (and for this sort of exercise to mean much, you'd probably want to print it out in hex both before writing it out, and after reading it back in, to show they match, and let the reader see a reasonable understandable representation of the file contents).

Change the endianness when reading from a file

I'm trying to get better understanding of endianness when someone read a file.
The machine i'm using is little endian.
The code down below is supposed to read any file type.
But what if the file we are reading is in UTF-16BE encoding, should we after reading the whole file change the endianness?
I'm asking this becouse i'm planing on editing the content of the file and output it in console.
In case we should change the endianness, how can that be done?
Right now i'm reading the files like this:
std::ifstream file("/RANDOME/PATH/file.html", std::ios::in | std::ios::binary);
std::string result;
file.seekg(0, std::ios::end);
result.reserve(t.tellg());
file.seekg(0, std::ios::beg);
result.assign((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
file.close();
I have no idea how to change the endianness from Big to little when reading a file. Can someone kindly show me step by step how that is done correctly?
i'm only trying to learn. I know the file is using UTF-16BE encoding that is not a guess.
Here is some code that does what you want. Note that this code reads the input file a line at a time rather than reading it all in one fell swoop.
#include <string>
#include <fstream>
void swap_bytes (char16_t *s)
{
while (*s)
{
unsigned char *uc = (unsigned char *) s;
unsigned char swap = *uc;
*uc = uc [1];
uc [1] = swap;
++s;
}
}
int main ()
{
std::basic_ifstream <char16_t> file ("/RANDOME/PATH/file.html", std::ios::in);
if (!file)
return 1;
std::basic_string <char16_t> line;
while (std::getline (file, line))
{
swap_bytes (line.data ());
// ...
}
file.close();
}
If anything is unclear please say so in the comments.
Live demo

Determine the size of a binary file

I'm trying to read a binary file and I need to determine its size, but regardless of the method I've tried, I'm getting a size of zero.
For example:
fstream cbf(address, ios::binary | ios::in | ios::ate);
fstream::pos_type size = cbf.tellg(); // Returns 0.
char* chunk = new char[size];
cbf.read(chunk, size);
//...
If I were to use the following:
#include <sys/stat.h>
struct stat st;
stat(address.c_str(),&st);
int size = st.st_size;
The size is still zero. I've also tried the following, but it's still zero.
File* fp;
fp = open(address.c_str(), "rb");
How do I get the size of the file?
Thanks for the responses... I've identified the problem:
The binary file I was trying to access was created during the execution, and I just had forgotten to close it before trying to read from it...
Neither of your examples checks for failure. This program, using your first method, works perfectly well for me. It correctly identifies the size of /etc/passwd and the non-existence of /etc/motd.
#include <fstream>
#include <iostream>
#include <string>
void printSize(const std::string& address) {
std::fstream motd(address.c_str(), std::ios::binary|std::ios::in|std::ios::ate);
if(motd) {
std::fstream::pos_type size = motd.tellg();
std::cout << address << " " << size << "\n";
} else {
perror(address.c_str());
}
}
int main () {
printSize("/etc/motd");
printSize("/etc/passwd");
}
Try to load the file in this method.
Note: Use ifstream insted of fstream in this line ifstream cbf(address, ios::binary | ios::in );
long size;
ifstream cbf(address, ios::binary | ios::in);
cbf.seekg(0, ios::end);
size=cbf.tellg();
cbf.seekg(0, ios::beg);
char* chunk = new char[size];
cbf.read(chunk, size);

I'm trying to set up a file stream or something like that, but I'm very confused as to what I'm supposed to do

#include <iostream>
#include <fstream>
int main() {
std::ofstream outfile("text.txt", ios::trunc);
std::ifstream infile("text.txt", ios::trunc);
outfile.seekp(0);
std::cout << "This is a file";
infile.seekg(0, ios::end);
int length = infile.tellg();
infile.read(0, length);
infile.close();
outfile.close();
return 0;
}
I think I get the idea behind this, but I feel like (and I'm pretty sure) I have no idea what I'm doing. I've looked it up and everything has confused me. I've read through a C++ reference, and then I googled it, but I still don't understand what I'm doing wrong.
#include <iostream>
#include <fstream>
#include <cstring>
int main() {
std::fstream file("text.txt", std::ios_base::in | std::ios_base::out);
file << "This is a file";
int length = file.tellg();
std::string uberstring;
file >> uberstring;
std::cout << uberstring;
char *buffer = new char[length + 1];
file.read(buffer, length);
buffer[length] = '\0';
file.close();
delete [] buffer;
return 0;
}
I tried this, but it isn't printing anything. Why isn't this working?
If you want to read and write to the same file, just use a normal std::fstream ... there is no need to attempt and open the same file as both a ifstream and ofstream. Also if you want to write data to the file, use the operator<< on the actual fstream instance object, not std::cout ... that will simply write to wherever std::cout is set, which is typically the console. Finally, the call to read has to go back into a buffer, you can't use NULL as an argument. So your code would change to the following:
int main()
{
std::fstream file("text.txt", ios_base::in | ios_base::out);
//outfile.seekp(0); <== not needed since you just opened the file
file << "This is a file"; //<== use the std::fstream instance "file"
//file.seekg(0, ios::end); <== not needed ... you're already at the end
int length = file.tellg();
//you have to read back into a buffer
char* buffer = new char[length + 1];
infile.read(buffer, length);
buffer[length] = '\0'; //<== NULL terminate the string
file.close();
delete [] buffer;
return 0;
}

Write to the middle of an existing binary file c++

I'm trying to open a binary file for writing without erasing the content. But I do not want to write to eof. I want to write to a specific position in file.
Here is a litte example:
ofstream out("test.txt", ios::binary | ios::app);
for(int i = 0; i < 100; i++)
out.put('_');
out.write("Hallo", 5);
out.close();
ofstream out2("test.txt", ios::binary | ios::app);
out2.seekp(10);
out2.write("Welt", 4);
out2.close();
If using app, seek doesn't work. If not using app opening file erases data. Does anybody know an answer?
try the second overload of seekp, which allows you to provide an offset and a direction, this could be begining of file in your case (i.e. ios_base::beg). This of course assumes you know what you are doing and all you want to do is overwrite an existing number of characters.
EDIT: here is fully working example:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
{
ofstream out("test.txt", ios::binary);
for(int i = 0; i < 100; i++)
out.put('_');
out.write("Hallo", 5);
}
{
fstream out2("test.txt", ios::binary | ios::out | ios::in);
out2.seekp(10, ios::beg);
out2.write("Welt", 4);
}
}
When opening with ios::app, it is as if you open a new file that just happened to be attached to an existing file: you can not access the existing file. I'm not sure, because I would do as in Kerrek's answer, but if you really want to try, you probably have to open with "ios::in | ios::out", similar to fopen("test.txt", "rw").
Or as crashmstr points out: ios::out might be enough.
You cannot magically extend the file from the middle. Perhaps easiest to write to a new file: First copy the initial segment, then write your new data, then copy the remaining segment. When all is done, you can overwrite the original file.
According to the specification of fstream here
fstream::open
the ios::app "Sets the stream's position indicator to the end of the stream before EACH output operation." So ios::app doesn't work for replacing, seeks of any sort fail, at least for me.
Just using ios::out does wipe out the file contents preserving only the size, basically turning the file into trash.
ios::in|ios::out turned out as the only working thing for me.
Working Code: This code searches for a string (OLD-STRING) in cout.exe and replaces with a new string (NEW-STRING).
`#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
fstream ifs;
ifs.open ("C:\\Users\\user\\Desktop\\cout.exe", fstream::binary | fstream::in | fstream::out);
std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
size_t pos = str.find("OLD-STRING");
if (pos != string::npos)
{
cout << "string found at position: " << int(pos) << endl;
ifs.seekp(pos);
ifs.write("NEW-STRING", 10);
}
else
{
cout << "could not find string" << endl;
}
if (ifs.is_open())
ifs.close();
return 0;
}`